您的位置:首页 > 运维架构 > Docker

使用Docker部署iRedmail

2015-09-22 14:35 821 查看
一 应用场景描述

现在需要搭建一个内部邮件服务器用于接收zabbix报警信息,邮件服务器选用iRedmail开源邮件系统。但是由于可用服务器不多,邮件服务器的使用压力也不大,于是考虑在一台空闲的物理机上安装KVM虚拟机或者Docker容器的方式来部署iRedmail邮件服务器。考虑到目前Docker容器很流行的,使用KVM虚拟机还要配置和管理KVM虚拟机,不如使用Docker容器来得方便。于是就有了这篇文章。

二 Docker基础知识
目前最新版本的Docker在CentOS6.5上运行不良,最好升级操作系统到CentOS7并升级内核到4.0以上,以下有说明。

在CentOS7上面安装Docker
yum -y install docker*

启动Docker服务
service docker start

获取最近的CentOS镜像
docker pull centos

获取CentOS6的镜像
docker pull centos:6

查看本地所有的镜像
docker images

查看单个镜像
docker images centos

docker run -v /usr/sbin:/usr/sbin --rm centos /usr/sbin/ip addr show--rm 容器停掉后会被删除

docker run -v /usr/sbin:/usr/sbin --name=test centos /usr/sbin/ip addr show --name 给容器改名字

docker start -i test 开启test容器

docker run --name=mybash -it centos /bin/bash可以在容器中安装软件yum -y install net-toolsdocker ps -a列出所有的容器docker ps 列出正在运行的容器docker start -ai mybash 开启容器docker run --name="log_test" -v /dev/log:/dev/log --rm centos logger "Testing logging to the host"
journalctl -b | grep Testing
docker inspect mybash 查看容器的元数据信息docker inspect --format='{{.NetworkSettings.IPAddress}}' mybashdocker inspect --format='{{.State.Pid}}' mybash
docker inspect --format='{{.HostConfig.PortBindings}}' mybash
docker exec 在一个运行中的容器中执行命令docker exec -it mybash /bin/bashdocker stop mybashdocker kill --signal="SIGHUP" mybash
docker rm goofy_wozniak
docker rm clever_yonath furious_shockley drunk_newton
d
docker run -i centos:6 /bin/bash -c "yum clean all;yum -y update;yum -y install -y httpd;yum clean all"docker ps -l 查看最近创建过的容器docker commit -m "centos6 with httpd" -a "john wang" ff0bfd94552a centos_httpd 从容器中创建镜像提交到本地镜像库docker run -d -p 8080:80 centos_httpd:latest /usr/sbin/httpd -DFOREGROUND 使用centos_httpd这个最新的镜像运行一个容器,映射容器的80端口到本地的8080端口
curl http://localhost:8080
从Dockerfile中创建镜像mkdir -p httpd-projectcd httpd-projectdocker build -t centos_httpd .docker run -d -t --name=mycentos_httpd -p 80:80 -i centos_httpd:latest /usr/sbin/httpd -DFOREGROUND从构建的镜像运行容器# netstat -tulnp|grep 80
tcp6 0 0 :::80 :::* LISTEN 26472/docker-proxy
# curl localhost:80Your Web server test is successful.docker tag 5c2ed3dea01f centos 给镜像打tag
docker tag 474ff279782b cnegus/myrhel7
docker save -o centos6.tar centos:latest 保存镜像为tar文件cat centos6.tar|docker import - john/centos6 docker rmi 340d0ced58bb 删除镜像
docker rmi $(docker images -a -q)  删除所有镜像


三 Docker网络知识
Docker启动后会默认创建一个名为docker0的虚拟网卡,一般是172.17.42.1/16,这个地址是可以变更的,创建一个容器的时候默认使用--net=bridge参数为容器分配一个docker0相同网段的IP。Docker创建一个容器的时候会创建一对对端网卡,一个分配给容器默认为eth0,一个绑定到docker0,名字一般是vethxxxx。详细知识请参考官方文档。

由于docker0默认为容器分配的IP不满足需求,我们配置的iredmail邮件服务器需要有内网网络的固定IP。所以这里要对docker的网络配置做些更改。
本文都是在CentOS7上安装Docker
1.在Docker主机重新创建一个桥接网卡
cd /etc/sysconfig/network-scripts/
cp ifcfg-enp4s0 ifcfg-br0

vim ifcfg-enp4s0
TYPE=Ethernet
BRIDGE=br0
BOOTPROTO=none
#IPADDR=172.28.10.125
#NETMASK=255.255.255.0
#GATEWAY=172.28.10.27
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME=enp4s0
UUID=5cabea9a-df74-4ac0-a8ae-42fb61357a09
DEVICE=enp4s0
ONBOOT=yes

vim ifcfg-br0

TYPE=Bridge
BOOTPROTO=static
IPADDR=172.28.10.125
NETMASK=255.255.255.0
GATEWAY=172.28.10.27
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME=br0
#UUID=5cabea9a-df74-4ac0-a8ae-42fb61357a09
DEVICE=br0
ONBOOT=yes

然后重新启动网卡
service network restart

查看网卡信息
# ifconfig
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.28.10.125 netmask 255.255.255.0 broadcast 172.28.10.255
inet6 fe80::1e6f:65ff:fed7:6531 prefixlen 64 scopeid 0x20<link>
ether 1c:6f:65:d7:65:31 txqueuelen 0 (Ethernet)
RX packets 371701 bytes 179614127 (171.2 MiB)
RX errors 0 dropped 24 overruns 0 frame 0
TX packets 104043 bytes 8964068 (8.5 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

enp4s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
ether 1c:6f:65:d7:65:31 txqueuelen 1000 (Ethernet)
RX packets 279799000 bytes 46612531640 (43.4 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 104058 bytes 8964998 (8.5 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 0 (Local Loopback)
RX packets 12 bytes 1124 (1.0 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 12 bytes 1124 (1.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

如果Docker已经启动,先关掉docker
service docker stop

vim /etc/sysconfig/docker
添加
OPTIONS='-b=br0 --selinux-enabled'
然后启动docker

service docker start
查看docker进程
ps -ef|grep docker
root 11358 1 0 09:00 ? 00:00:00 /usr/bin/docker -d -b=br0 --selinux-enabled

docker会修改iptables的nat表
# iptables -t nat -L -n
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.28.10.0/24 0.0.0.0/0

创建一个CentOS6的容器用于安装iredmail

#docker run -it --net=none --name=iredmail --hostname=mx.xxx.com --add-host=mx.xxx.com:127.0.0.1 --privileged=true centos:6 /bin/bash
--name 指定容器的名称
--hostname 指定容器的主机名,生成容器后没法在容器内部修改主机名,修改容器的容器的配置文件也无法生效,所以创建容器的时候最好指定主机名

进入iredmail容器
# docker exec -it iredmail /bin/bash

[root@7e34924492f3 /]# ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)

由于创建iredmail容器的时候使用的是--net=none,docker将不会为这个容器分配IP地址
根据官方文档的步骤我写了个脚本可以自动为iredmail容器添加固定IP。
docker_container_ip.sh
#!/bin/bash
#author: john wang
#this script is used to auto add specified private ip for docker container

#container can be id or name such as 7e34924492f3  or iredmail

container=iredmail
bridge=br0
mac=12:34:56:78:9a:bc
ip=172.28.10.72/24
gateway=172.28.10.27

docker_status=$(ps -ef|grep docker|grep $bridge|grep -v grep|grep -v $0)
if [ "$docker_status" == "" ];then
echo -e "\e[035mDocker is not running\e[0m"
echo -e "\e[035mStarting docker\e[0m"
/sbin/service docker start
else
echo -e "\e[035mDocker is already running\e[0m"
fi

container_status=$(docker ps|grep $container)

function set_ip () {
echo -e "\e[035m set ip $ip gateway $gateway mac $mac  for  $container\e[0m"
#### set_ip $1
####
id=$(docker ps|grep $container|awk '{print $1}')
if [ "$id" != "" ];then
A=veth${id:0:4}
B=eth${id:0:4}
###  Error: argument "veth7e34924492f3" is wrong: "name" too long
### use ${id:0:4} to cut container id, only  use prefix 4 characters

pid=$1
mkdir -p /var/run/netns
ln -sf /proc/$pid/ns/net  /var/run/netns/$pid   > /dev/null

###########
####   /opt/script/docker_container_ip.sh: line 43: ip: command not found
####   /opt/script/docker_container_ip.sh: line 44: brctl: command not found
####   tail -f /var/spool/mail/root
####
###########

/usr/sbin/ip link add $A  type veth   peer name   $B  > /dev/null  2>&1
/usr/sbin/brctl addif $bridge $A            > /dev/null  2>&1
/usr/sbin/ip link set $A up                 > /dev/null  2>&1

/usr/sbin/ip link set $B  netns $pid    > /dev/null  2>&1
/usr/sbin/ip netns exec $pid ip link set dev $B name eth0    > /dev/null 2>&1
/usr/sbin/ip netns exec $pid ip link set eth0 address $mac    > /dev/null  2>&1
/usr/sbin/ip netns exec $pid ip link set eth0 up              > /dev/null  2>&1
/usr/sbin/ip netns exec $pid ip addr add $ip dev eth0         > /dev/null  2>&1
/usr/sbin/ip netns exec $pid ip route add default via $gateway  > /dev/null 2>&1
### 2>&1
else
echo -e "\e[035mContainer ID is not valid\e[0m"
fi

}

if [ "$container_status" != "" -a "$docker_status" != "" ];then
#create a pair of peer interfaces A and B
#bind the A end to the bridge,and bring it up
#place B inside the container's network namespace
#rename to eht0,and activate it with a free IP
pid=$(docker inspect -f '{{.State.Pid}}' $container)
set_ip $pid
else
echo -e "\e[035m **********WARNING   container $container is not running **********\e[0m"
echo -e "\e[035m **********Starting  container $container\e[0m"
docker start $container
pid=$(docker inspect -f '{{.State.Pid}}' $container)
set_ip $pid
fi


添加定时任务
*/2 * * * * /opt/script/docker_container_ip.sh >> /tmp/docker_container_ip.log

这样就可以避免iredmail容器重启或者docker重新启动后容器内的IP消失
root@mx /]# ifconfig
eth0      Link encap:Ethernet  HWaddr 12:34:56:78:9A:BC
inet addr:172.28.10.72  Bcast:0.0.0.0  Mask:255.255.255.0
inet6 addr: fe80::1034:56ff:fe78:9abc/64 Scope:Link
UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
RX packets:7642 errors:0 dropped:0 overruns:0 frame:0
TX packets:517 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:618391 (603.8 KiB)  TX bytes:39509 (38.5 KiB)

lo        Link encap:Local Loopback
inet addr:127.0.0.1  Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING  MTU:65536  Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

[root@mx /]# hostname


使用CentOS7默认的内核运行Docker时会莫名其妙出现内核报错,导致CentOS重启后无法启动
升级内核到4.2.3解决这个问题
参考文章
/article/4255607.html

四 安装和配置iredmail

然后参考/article/4405092.html这里的步骤安装和配置iredmail
按照配置完iredmail后需要启动相关服务,安装后iredmail后提示重启启动服务器,但是使用Docker容器重启后并不会自动启动相关服务
执行脚本/opt/script/iredmail_service.sh
#!/bin/bash
services="amavisd cbpolicyd clamd clamd.amavisd crond dovecot httpd iredapd mysqld postfix rsyslog saslauthd slapd spamassassin sshd iptables"

for i in $(echo $services)
do
service $i start
done


测试可以使用后就可以使用docker commit将这个运行的iredmail容器制作成镜像提交到本地镜像库

docker commit -m "centos with iredmail" -a "john wang" 3fffabaa79cd centos_iredmail

五 从Dockerfile中创建iredmail镜像
可以使用Dockerfile创建iredmail镜像
mkdir -p docker_iredmail
cd docker_iredmail/
vim Dockerfile

FROM centos:6

### Update and customize centos packages.
RUN yum -y install wget vim lrzsz tar bzip2 telnet man

### Download and unzip iRedMail.
ENV IREDMAIL iRedMail-0.9.2
RUN wget https://bitbucket.org/zhb/iredmail/downloads/$IREDMAIL.tar.bz2 ;\
tar xvjf $IREDMAIL.tar.bz2 ;\
rm $IREDMAIL.tar.bz2
RUN rpm -ivh http://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm 
### Install iRedMail.
RUN  echo "127.0.0.1 mx.xxx.com" > /etc/hosts
#RUN  hostname mx.xxx.com
COPY depends.txt /$IREDMAIL/
COPY config /$IREDMAIL/
RUN  for i in $(cat /$IREDMAIL/depends.txt);\
do \
yum -y install $i;\
done

RUN chmod +x /$IREDMAIL/iRedMail.sh
RUN echo y | /$IREDMAIL/iRedMail.sh


vim depends.txt
这个文件是安装和配置iredmail需要的软件包
MySQL-python
acl
altermime
amavisd-new
awstats
clamav-db
clamd
cluebringer
crontabs
dos2unix
dovecot
dovecot-managesieve
dovecot-pigeonhole
fail2ban
httpd
logwatch
mod_ssl
mod_wsgi
mysql-server
openldap-clients
openldap-servers
patch
perl-LDAP
perl-Mail-SPF
php
php-common
php-gd
php-imap
php-intl
php-ldap
php-mbstring
php-mcrypt
php-mysql
php-pear-Net-IDNA2
php-pear-Net-LDAP2
php-pecl-apc
php-pgsql
php-xml
postfix
python-beautifulsoup4
python-jinja2
python-ldap
python-lxml
python-netifaces
python-setuptools
python-sqlalchemy
python-webpy
spamassassin
tmpwatch
unrar
unzip
openldap
apr
apr-util
apr-util-ldap
arj
cabextract
clamav
cronie
cronie-anacron
cyrus-sasl
db4-cxx
db4-devel
ed
file
freeze
gamin-python
gdbm-devel
glibc-devel
glibc-headers
httpd-tools
ipset
kernel-headers
libXpm
libc-client
libicu
libmcrypt
libmnl
libmspack
libtool-ltdl
libxslt
logrotate
lrzip
lzo
lzop
mailcap
mailx
mysql
mysql-libs
nomarch
p7zip
p7zip-plugins
perl
perl-Archive-Tar
perl-Archive-Zip
perl-Authen-SASL
perl-BerkeleyDB
perl-Cache-FastMmap
perl-Compress-Raw-Zlib
perl-Compress-Zlib
perl-Config-IniFiles
perl-Convert-ASN1
perl-Convert-BinHex
perl-Convert-TNEF
perl-Convert-UUlib
perl-Crypt-OpenSSL-Bignum
perl-Crypt-OpenSSL-RSA
perl-Crypt-OpenSSL-Random
perl-DBD-MySQL
perl-DBD-SQLite
perl-DBI
perl-Date-Manip
perl-Digest-HMAC
perl-Digest-SHA
perl-Digest-SHA1
perl-Encode-Detect
perl-Error
perl-ExtUtils-MakeMaker
perl-ExtUtils-ParseXS
perl-GSSAPI
perl-HTML-Parser
perl-HTML-Tagset
perl-IO-Compress-Base
perl-IO-Compress-Zlib
perl-IO-Multiplex
perl-IO-Socket-INET6
perl-IO-Socket-SSL
perl-IO-Zlib
perl-IO-stringy
perl-List-MoreUtils
perl-MIME-tools
perl-Mail-DKIM
perl-MailTools
perl-Module-Pluggable
perl-Net-DNS
perl-Net-LibIDN
perl-Net-SSLeay
perl-Net-Server
perl-NetAddr-IP
perl-Package-Constants
perl-Pod-Escapes
perl-Pod-Simple
perl-Razor-Agent
perl-Socket6
perl-Test-Harness
perl-Text-Iconv
perl-Time-HiRes
perl-TimeDate
perl-URI
perl-Unix-Syslog
perl-XML-Filter-BufferText
perl-XML-LibXML
perl-XML-NamespaceSupport
perl-XML-SAX
perl-XML-SAX-Writer
perl-YAML-Syck
perl-devel
perl-libs
perl-libwww-perl
perl-version
php-cli
php-pdo
php-pear
portreserve
postgresql-libs
procmail
python-babel
python-cherrypy
python-html5lib
python-inotify
redhat-logos
rsyslog
unzoo
db4
db4-utils
glibc
glibc-common


参考文章:
https://docs.docker.com/articles/networking/
https://github.com/docker-build/iRedMail
https://hub.docker.com/search/?q=iRedMail&page=1&isAutomated=0&isOfficial=0&starCount=0&pullCount=0
/article/4405092.html
/article/4255607.html

本文出自 “Linux SA John” 博客,请务必保留此出处http://john88wang.blog.51cto.com/2165294/1697087
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: