Docker使用 Supervisor 来管理进程
Docker 容器在启动的时候开启单个进程,比如,一个 ssh 或者 apache 的 daemon 服务。但我们经常需要在一个机器上开启多个服务,这可以有很多方法,最简单的就是把多个启动命令放到一个启动脚本里面,启动的时候直接启动这个脚本,另外就是安装进程管理工具。 | |
---|---|
配置
首先创建一个 Dockerfile,内容和各部分的解释如下。
FROM ubuntu:13.04
MAINTAINER examples@docker.com
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
RUN apt-get upgrade -y
安装 ssh、apache 和 supervisor
RUN apt-get install -y openssh-server apache2 supervisor
RUN mkdir -p /var/run/sshd
RUN mkdir -p /var/log/supervisor`
这里安装 3 个软件,还创建了 2 个 ssh 和 supervisor 服务正常运行所需要的目录。
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
添加 supervisord 的配置文件,并复制配置文件到对应目录下面。
EXPOSE 22 80
CMD ["/usr/bin/supervisord"]
这里我们映射了 22 和 80 端口,使用 supervisord 的可执行路径启动服务。
supervisor配置文件内容
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
[program:apache2]
command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2 -DFOREGROUND"
配置文件包含目录和进程,第一段 supervsord 配置软件本身,使用 nodaemon 参数来运行。第二段包含要控制的 2 个服务。每一段包含一个服务的目录和启动这个服务的命令。 | |
---|---|
使用方法
创建镜像。
$ sudo docker build -t test/supervisord .
启动 supervisor 容器。
$ sudo docker run -p 22 -p 80 -t -i test/supervisords
2013-11-25 18:53:22,312 CRIT Supervisor running as root (no user in config file)
2013-11-25 18:53:22,312 WARN Included extra file "/etc/supervisor/conf.d/supervisord.conf" during parsing
2013-11-25 18:53:22,342 INFO supervisord started with pid 1
2013-11-25 18:53:23,346 INFO spawned: 'sshd' with pid 6
2013-11-25 18:53:23,349 INFO spawned: 'apache2' with pid 7
使用 docker run 来启动我们创建的容器
。使用多个 -p 来映射多个端口,这样我们就能同时访问 ssh 和 apache 服务了。
可以使用这个方法创建一个只有 ssh 服务的基础镜像,之后创建镜像可以使用这个镜像为基础来创建
Docker创建 tomcat/weblogic 集群
安装 tomcat 镜像
准备好需要的 jdk、tomcat 等软件放到 home 目录下面,启动一个容器
docker run -t -i -v /home:/opt/data --name mk_tomcat ubuntu /bin/bash
这条命令挂载本地 home 目录到容器的 /opt/data 目录,容器内目录若不存在,则会自动创建。接下来就是 tomcat 的基本配置,jdk 环境变量设置好之后,将 tomcat 程序放到 /opt/apache-tomcat 下面 编辑 /etc/supervisor/conf.d/supervisor.conf 文件,添加 tomcat 项
[supervisord]
nodaemon=true
[program:tomcat]
command=/opt/apache-tomcat/bin/startup.sh
[program:sshd]
command=/usr/sbin/sshd -D
docker commit ac6474aeb31d tomcat
新建 tomcat 文件夹,新建 Dockerfile。
FROM mk_tomcat
EXPOSE 22 8080
CMD ["/usr/bin/supervisord"]
根据 Dockerfile 创建镜像。
docker build tomcat tomcat
安装 weblogic 镜像
步骤和 tomcat 基本一致,这里贴一下配置文件
supervisor.conf
[supervisord]
nodaemon=true
[program:weblogic]
command=/opt/Middleware/user_projects/domains/base_domain/bin/startWebLogic.sh
[program:sshd]
command=/usr/sbin/sshd -D
dockerfile
FROM weblogic
EXPOSE 22 7001
CMD ["/usr/bin/supervisord"]
tomcat/weblogic 镜像的使用
存储的使用
在启动的时候,使用 -v 参数
-v, --volume=[] Bind mount a volume (e.g. from the host:
-v /host:/container, from docker: -v /container)
将本地磁盘映射到容器内部,它在主机和容器之间是实时变化的
,所以我们更新程序、上传代码只需要更新物理主机的目录就可以了
tomcat 和 weblogic 集群的实现
tomcat 只要开启多个容器即可
docker run -d -v -p 204:22 -p 7003:8080 -v /home/data:/opt/data --name tm1 tomcat /usr/bin/supervisord
docker run -d -v -p 205:22 -p 7004:8080 -v /home/data:/opt/data --name tm2 tomcat /usr/bin/supervisord
docker run -d -v -p 206:22 -p 7005:8080 -v /home/data:/opt/data --name tm3 tomcat /usr/bin/supervisord
这里说一下 weblogic 的配置,大家知道 weblogic 有一个域的概念。如果要使用常规的 administrator +node 的方式部署,就需要在 supervisord 中分别写出 administartor server 和 node server 的启动脚本,这样做的优点是:
可以使用 weblogic 的集群,同步等概念
部署一个集群应用程序,只需要安装一次应用到集群上即可
缺点是:
Docker 配置复杂了
没办法自动扩展集群的计算容量,如需添加节点,需要在 administrator 上先创建节点,然后再配置新的容器 supervisor 启动脚本,然后再启动容器
另外种方法是将所有的程序都安装在 adminiserver 上面,需要扩展的时候,启动多个节点即可,它的优点和缺点和上一种方法恰恰相反。(建议使用这种方式来部署开发和测试环境) | |
---|---|
docker run -d -v -p 204:22 -p 7001:7001 -v /home/data:/opt/data --name node1 weblogic /usr/bin/supervisord
docker run -d -v -p 205:22 -p 7002:7001 -v /home/data:/opt/data --name node2 weblogic /usr/bin/supervisord
docker run -d -v -p 206:22 -p 7003:7001 -v /home/data:/opt/data --name node3 weblogic /usr/bin/supervisord
这样在前端使用 nginx 来做负载均衡就可以完成配置了
Docker多台物理主机之间的容器互联
Docker 默认的桥接网卡是 docker0。它只会在本机桥接所有的容器网卡,举例来说容器的虚拟网卡在主机上看一般叫做 veth 而 Docker 只是把所有这些网卡桥接在一起,如下:*
[root@opnvz ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.56847afe9799 no veth0889
veth3c7b
veth4061
在容器中看到的地址一般是像下面这样的地址:
root@ac6474aeb31d:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
11: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 4a:7d:68:da:09:cf brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::487d:68ff:feda:9cf/64 scope link
valid_lft forever preferred_lft forever
这样就可以把这个网络看成是一个私有的网络,通过 nat 连接外网
,如果要让外网连接到容器中,就需要做端口映射,即 -p 参数。
如果在企业内部应用,或者做多个物理主机的集群,可能需要将多个物理主机的容器组到一个物理网络中来,那么就需要将这个网桥桥接到我们指定的网卡上。 | |
---|---|
拓扑图
主机 A 和主机 B 的网卡一都连着物理交换机的同一个 vlan 101,这样网桥一和网桥三就相当于在同一个物理网络中了,而容器一、容器三、容器四也在同一物理网络中了,他们之间可以相互通信,而且可以跟同一 vlan 中的其他物理机器互联。
ubuntu 示例
下面以 ubuntu 为例创建多个主机的容器联网: 创建自己的网桥,编辑 /etc/network/interface 文件
auto br0
iface br0 inet static
address 192.168.7.31
netmask 255.255.240.0
gateway 192.168.7.254
bridge_ports em1
bridge_stp off
dns-nameservers 8.8.8.8 192.168.6.1
将 Docker 的默认网桥绑定到这个新建的 br0 上面,这样就将这台机器上容器绑定到 em1 这个网卡所对应的物理网络上了。
ubuntu 修改 /etc/default/docker 文件
,添加最后一行内容
# Docker Upstart and SysVinit configuration file
# Customize location of Docker binary (especially for development testing).
#DOCKER="/usr/local/bin/docker"
# Use DOCKER_OPTS to modify the daemon startup options.
#DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4"
# If you need Docker to use an HTTP proxy, it can also be specified here.
#export http_proxy="http://127.0.0.1:3128/"
# This is also a handy place to tweak where Docker's temporary files go.
#export TMPDIR="/mnt/bigdrive/docker-tmp"
DOCKER_OPTS="-b=br0"
在启动 Docker 的时候 使用 -b 参数 将容器绑定到物理网络上
。重启 Docker 服务后,再进入容器可以看到它已经绑定到你的物理网络上了。
root@ubuntudocker:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
58b043aa05eb desk_hz:v1 "/startup.sh" 5 days ago Up 2 seconds 5900/tcp, 6080/tcp, 22/tcp yanlx
root@ubuntudocker:~# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.7e6e617c8d53 no em1
vethe6e5
这样就直接把容器暴露到物理网络上了,多台物理主机的容器也可以相互联网了。需要注意的是,这样就需要自己来保证容器的网络安全了。 | |
---|---|
Docker标准化开发测试和生产环境
对于大部分企业来说,搭建 PaaS 既没有那个精力,也没那个必要,用 Docker 做个人的 sandbox 用处又小了点。
可以用 Docker 来标准化开发、测试、生产环境。
企业应用结构
Docker 占用资源小,在一台 E5 128 G 内存的服务器上部署 100 个容器都绰绰有余,可以单独抽一个容器或者直接在宿主物理主机上部署 samba,利用 samba 的 home 分享方案将每个用户的 home 目录映射到开发中心和测试部门的 Windows 机器上。
针对某个项目组,由架构师搭建好一个标准的容器环境供项目组和测试部门使用,每个开发工程师可以拥有自己单独的容器,通过 docker run -v 将用户的 home 目录映射到容器中
。需要提交测试时,只需要将代码移交给测试部门,然后分配一个容器使用 -v 加载测试部门的 home 目录启动即可。这样,在公司内部的开发、测试基本就统一了,不会出现开发部门提交的代码,测试部门部署不了的问题。
测试部门发布测试通过的报告后,架构师再一次检测容器环境,就可以直接交由部署工程师将代码和容器分别部署到生产环境中了。这种方式的部署横向性能的扩展性也极好。