Docker —— 从入门到实践(完)
10. 实战案例
介绍一些典型的应用场景和案例。
10.1. 使用 Supervisor 来管理进程
Docker 容器在启动的时候开启单个进程,比如,一个 ssh 或者 apache 的 daemon 服务。但我们经常需要在一个机器上开启多个服务,这可以有很多方法,最简单的就是把多个启动命令方到一个启动脚本里面,启动的时候直接启动这个脚本,另外就是安装进程管理工具。
本小节将使用进程管理工具 supervisor 来管理容器中的多个进程。使用 Supervisor 可以更好的控制、管理、重启我们希望运行的进程。在这里我们演示一下如何同时使用 ssh 和 apache 服务。
配置
首先创建一个 Dockerfile,内容和各部分的解释如下。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >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 de>
安装 supervisor
安装 ssh、apache 和 supervisor。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >RUN apt-get install -y openssh-server apache2 supervisor RUN mkdir -p /var/run/sshd RUN mkdir -p /var/log/supervisor de>
这里安装 3 个软件,还创建了 2 个 ssh 和 supervisor 服务正常运行所需要的目录。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf de>
添加 supervisord 的配置文件,并复制配置文件到对应目录下面。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >EXPOSE 22 80 CMD ["/usr/bin/supervisord"] de>
这里我们映射了 22 和 80 端口,使用 supervisord 的可执行路径启动服务。
supervisor配置文件内容
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >[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" de>
配置文件包含目录和进程,第一段 supervsord 配置软件本身,使用 nodaemon 参数来运行。第二段包含要控制的 2 个服务。每一段包含一个服务的目录和启动这个服务的命令。
使用方法
创建镜像。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker build -t test/supervisord . de>
启动 supervisor 容器。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ 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 de>
使用
可以使用这个方法创建一个只有 ssh 服务的基础镜像,之后创建镜像可以使用这个镜像为基础来创建
10.2. 创建 tomcat/weblogic 集群
安装 tomcat 镜像
准备好需要的 jdk、tomcat 等软件放到 home 目录下面,启动一个容器
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >docker run -t -i -v /home:/opt/da ta --name mk_tomcat ubuntu /bin/bash de>
这条命令挂载本地 home 目录到容器的 /opt/da
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >[supervisord] nodaemon=true [program:tomcat] command=/opt/apache-tomcat/bin/startup.sh [program:sshd] command=/usr/sbin/sshd -D docker commit ac6474aeb31d tomcat de>
新建 tomcat 文件夹,新建 Dockerfile。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >FROM mk_tomcat EXPOSE 22 8080 CMD ["/usr/bin/supervisord"] de>
根据 Dockerfile 创建镜像。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >docker build tomcat tomcat de>
安装 weblogic 镜像
步骤和 tomcat 基本一致,这里贴一下配置文件
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >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"] de>
tomcat/weblogic 镜像的使用
存储的使用
在启动的时候,使用
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >-v, --volume=[] Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container) de>
将本地磁盘映射到容器内部,它在主机和容器之间是实时变化的,所以我们更新程序、上传代码只需要更新物理主机的目录就可以了
tomcat 和 weblogic 集群的实现
tomcat 只要开启多个容器即可
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >docker run -d -v -p 204:22 -p 7003:8080 -v /home/da ta:/opt/da ta --name tm1 tomcat /usr/bin/supervisord docker run -d -v -p 205:22 -p 7004:8080 -v /home/da ta:/opt/da ta --name tm2 tomcat /usr/bin/supervisord docker run -d -v -p 206:22 -p 7005:8080 -v /home/da ta:/opt/da ta --name tm3 tomcat /usr/bin/supervisord de>
这里说一下 weblogic 的配置,大家知道 weblogic 有一个域的概念。如果要使用常规的 administrator +node 的方式部署,就需要在 supervisord 中分别写出 administartor server 和 node server 的启动脚本,这样做的优点是:
- 可以使用 weblogic 的集群,同步等概念
- 部署一个集群应用程序,只需要安装一次应用到集群上即可
缺点是:
- Docker 配置复杂了
- 没办法自动扩展集群的计算容量,如需添加节点,需要在 administrator 上先创建节点,然后再配置新的容器 supervisor 启动脚本,然后再启动容器 另外种方法是将所有的程序都安装在 adminiserver 上面,需要扩展的时候,启动多个节点即可,它的优点和缺点和上一种方法恰恰相反。(建议使用这种方式来部署开发和测试环境)
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >docker run -d -v -p 204:22 -p 7001:7001 -v /home/da ta:/opt/da ta --name node1 weblogic /usr/bin/supervisord docker run -d -v -p 205:22 -p 7002:7001 -v /home/da ta:/opt/da ta --name node2 weblogic /usr/bin/supervisord docker run -d -v -p 206:22 -p 7003:7001 -v /home/da ta:/opt/da ta --name node3 weblogic /usr/bin/supervisord de>
这样在前端使用 nginx 来做负载均衡就可以完成配置了
10.3. 多台物理主机之间的容器互联(暴露容器到真实网络中)
Docker 默认的桥接网卡是 docker0。它只会在本机桥接所有的容器网卡,举例来说容器的虚拟网卡在主机上看一般叫做 veth* 而 Docker 只是把所有这些网卡桥接在一起,如下:
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >[root@opnvz ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.56847afe9799 no veth0889 veth3c7b veth4061 de>
在容器中看到的地址一般是像下面这样的地址:
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >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 de>
这样就可以把这个网络看成是一个私有的网络,通过 nat 连接外网,如果要让外网连接到容器中,就需要做端口映射,即 -p 参数。
如果在企业内部应用,或者做多个物理主机的集群,可能需要将多个物理主机的容器组到一个物理网络中来,那么就需要将这个网桥桥接到我们指定的网卡上。
拓扑图
主机 A 和主机 B 的网卡一都连着物理交换机的同一个 vlan 101,这样网桥一和网桥三就相当于在同一个物理网络中了,而容器一、容器三、容器四也在同一物理网络中了,他们之间可以相互通信,而且可以跟同一 vlan 中的其他物理机器互联。
ubuntu 示例
下面以 ubuntu 为例创建多个主机的容器联网: 创建自己的网桥,编辑 /etc/network/interface 文件
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >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 de>
将 Docker 的默认网桥绑定到这个新建的 br0 上面,这样就将这台机器上容器绑定到 em1 这个网卡所对应的物理网络上了。
ubuntu 修改 /etc/default/docker 文件,添加最后一行内容
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" ># 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" de>
在启动 Docker 的时候 使用 -b 参数 将容器绑定到物理网络上。重启 Docker 服务后,再进入容器可以看到它已经绑定到你的物理网络上了。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >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 de>
这样就直接把容器暴露到物理网络上了,多台物理主机的容器也可以相互联网了。需要注意的是,这样就需要自己来保证容器的网络安全了。
10.4. 标准化开发测试和生产环境
对于大部分企业来说,搭建 PaaS 既没有那个精力,也没那个必要,用 Docker 做个人的 sandbox 用处又小了点。
可以用 Docker 来标准化开发、测试、生产环境。
Docker 占用资源小,在一台 E5 128 G 内存的服务器上部署 100 个容器都绰绰有余,可以单独抽一个容器或者直接在宿主物理主机上部署 samba,利用 samba 的 home 分享方案将每个用户的 home 目录映射到开发中心和测试部门的 Windows 机器上。
针对某个项目组,由架构师搭建好一个标准的容器环境供项目组和测试部门使用,每个开发工程师可以拥有自己单独的容器,通过
测试部门发布测试通过的报告后,架构师再一次检测容器环境,就可以直接交由部署工程师将代码和容器分别部署到生产环境中了。这种方式的部署横向性能的扩展性也极好。
11. 安全
评估 Docker 的安全性时,主要考虑三个方面:
- 由内核的名字空间和控制组机制提供的容器内在安全
- Docker程序(特别是服务端)本身的抗攻击性
- 内核安全性的加强机制对容器安全性的影响
11.1. 内核名字空间
Docker 容器和 LXC 容器很相似,所提供的安全特性也差不多。当用
名字空间提供了最基础也是最直接的隔离,在容器中运行的进程不会被运行在主机上的进程和其它容器发现和作用。
每个容器都有自己独有的网络栈,意味着它们不能访问其他容器的 sockets 或接口。不过,如果主机系统上做了相应的设置,容器可以像跟主机交互一样的和其他容器交互。当指定公共端口或使用 links 来连接 2 个容器时,容器就可以相互通信了(可以根据配置来限制通信的策略)。
从网络架构的角度来看,所有的容器通过本地主机的网桥接口相互通信,就像物理机器通过物理交换机通信一样。
那么,内核中实现名字空间和私有网络的代码是否足够成熟?
内核名字空间从 2.6.15 版本(2008 年 7 月发布)之后被引入,数年间,这些机制的可靠性在诸多大型生产系统中被实践验证。
实际上,名字空间的想法和设计提出的时间要更早,最初是为了在内核中引入一种机制来实现 OpenVZ 的特性。 而 OpenVZ 项目早在 2005 年就发布了,其设计和实现都已经十分成熟。
11.2. 控制组
控制组是 Linux 容器机制的另外一个关键组件,负责实现资源的审计和限制。
它提供了很多有用的特性;以及确保各个容器可以公平地分享主机的内存、CPU、磁盘 IO 等资源;当然,更重要的是,控制组确保了当容器内的资源使用产生压力时不会连累主机系统。
尽管控制组不负责隔离容器之间相互访问、处理数据和进程,它在防止拒绝服务(DDOS)攻击方面是必不可少的。尤其是在多用户的平台(比如公有或私有的 PaaS)上,控制组十分重要。例如,当某些应用程序表现异常的时候,可以保证一致地正常运行和性能。
控制组机制始于 2006 年,内核从 2.6.24 版本开始被引入。
11.3. Docker服务端的防护
运行一个容器或应用程序的核心是通过 Docker 服务端。Docker 服务的运行目前需要 root 权限,因此其安全性十分关键。
首先,确保只有可信的用户才可以访问 Docker 服务。Docker 允许用户在主机和容器间共享文件夹,同时不需要限制容器的访问权限,这就容易让容器突破资源限制。例如,恶意用户启动容器的时候将主机的根目录
这将会造成很严重的安全后果。因此,当提供容器创建服务时(例如通过一个 web 服务器),要更加注意进行参数的安全检查,防止恶意的用户用特定参数来创建一些破坏性的容器
为了加强对服务端的保护,Docker 的 REST API(客户端用来跟服务端通信)在 0.5.2 之后使用本地的 Unix 套接字机制替代了原先绑定在 127.0.0.1 上的 TCP 套接字,因为后者容易遭受跨站脚本攻击。现在用户使用 Unix 权限检查来加强套接字的访问安全。
用户仍可以利用 HTTP 提供 REST API 访问。建议使用安全机制,确保只有可信的网络或 VPN,或证书保护机制(例如受保护的 stunnel 和 ssl 认证)下的访问可以进行。此外,还可以使用 HTTPS 和证书来加强保护。
最近改进的 Linux 名字空间机制将可以实现使用非 root 用户来运行全功能的容器。这将从根本上解决了容器和主机之间共享文件系统而引起的安全问题。
终极目标是改进 2 个重要的安全特性:
- 将容器的 root 用户映射到本地主机上的非 root 用户,减轻容器和主机之间因权限提升而引起的安全问题;
- 允许 Docker 服务端在非 root 权限下运行,利用安全可靠的子进程来代理执行需要特权权限的操作。这些子进程将只允许在限定范围内进行操作,例如仅仅负责虚拟网络设定或文件系统管理、配置操作等。
最后,建议采用专用的服务器来运行 Docker 和相关的管理服务(例如管理服务比如 ssh 监控和进程监控、管理工具 nrpe、collectd 等)。其它的业务服务都放到容器中去运行。
11.4. 内核能力机制
能力机制(Capability)是 Linux 内核一个强大的特性,可以提供细粒度的权限访问控制。 Linux 内核自 2.2 版本起就支持能力机制,它将权限划分为更加细粒度的操作能力,既可以作用在进程上,也可以作用在文件上。
例如,一个 Web 服务进程只需要绑定一个低于 1024 的端口的权限,并不需要 root 权限。那么它只需要被授权
默认情况下,Docker 启动的容器被严格限制只允许使用内核的一部分能力。
使用能力机制对加强 Docker 容器的安全有很多好处。通常,在服务器上会运行一堆需要特权权限的进程,包括有 ssh、cron、syslogd、硬件管理工具模块(例如负载模块)、网络配置工具等等。容器跟这些进程是不同的,因为几乎所有的特权进程都由容器以外的支持系统来进行管理。
- ssh 访问被主机上ssh服务来管理;
- cron 通常应该作为用户进程执行,权限交给使用它服务的应用来处理;
- 日志系统可由 Docker 或第三方服务管理;
- 硬件管理无关紧要,容器中也就无需执行 udevd 以及类似服务;
- 网络管理也都在主机上设置,除非特殊需求,容器不需要对网络进行配置。
从上面的例子可以看出,大部分情况下,容器并不需要“真正的” root 权限,容器只需要少数的能力即可。为了加强安全,容器可以禁用一些没必要的权限。
- 完全禁止任何 mount 操作;
- 禁止直接访问本地主机的套接字;
- 禁止访问一些文件系统的操作,比如创建新的设备、修改文件属性等;
- 禁止模块加载。
这样,就算攻击者在容器中取得了 root 权限,也不能获得本地主机的较高权限,能进行的破坏也有限。
默认情况下,Docker采用 白名单 机制,禁用 必需功能 之外的其它权限。 当然,用户也可以根据自身需求来为 Docker 容器启用额外的权限。
11.5. 其它安全特性
除了能力机制之外,还可以利用一些现有的安全机制来增强使用 Docker 的安全性,例如 TOMOYO, AppArmor, SELinux, GRSEC 等。
Docker 当前默认只启用了能力机制。用户可以采用多种方案来加强 Docker 主机的安全,例如:
- 在内核中启用 GRSEC 和 PAX,这将增加很多编译和运行时的安全检查;通过地址随机化避免恶意探测等。并且,启用该特性不需要 Docker 进行任何配置。
- 使用一些有增强安全特性的容器模板,比如带 AppArmor 的模板和 Redhat 带 SELinux 策略的模板。这些模板提供了额外的安全特性。
- 用户可以自定义访问控制机制来定制安全策略。
跟其它添加到 Docker 容器的第三方工具一样(比如网络拓扑和文件系统共享),有很多类似的机制,在不改变 Docker 内核情况下就可以加固现有的容器。
11.6. 总结
总体来看,Docker 容器还是十分安全的,特别是在容器内不使用 root 权限来运行进程的话。
另外,用户可以使用现有工具,比如 Apparmor, SELinux, GRSEC 来增强安全性;甚至自己在内核中实现更复杂的安全机制。
12. Dockerfile
使用 Dockerfile 可以允许用户创建自定义的镜像。
12.1. 基本结构
Dockerfile 由一行行命令语句组成,并且支持以
一般的,Dockerfile 分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。
例如
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" ># This dockerfile uses the ubuntu image # VERSION 2 - EDITION 1 # Author: docker_user # Command format: Instruction [arguments / command] .. # Base image to use, this must be set as the first line FROM ubuntu # Maintainer: docker_user <docker_user at email.com> (@docker_user) MAINTAINER docker_user docker_user@email.com # Commands to update the image RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list RUN apt-get update && apt-get install -y nginx RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf # Commands when creating a new container CMD /usr/sbin/nginx de>
其中,一开始必须指明所基于的镜像名称,接下来推荐说明维护者信息。
后面则是镜像操作指令,例如
最后是
下面是一个更复杂的例子
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" ># Nginx # # VERSION 0.0.1 FROM ubuntu MAINTAINER Victor Vieux <victor@docker.com> RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server # Firefox over VNC # # VERSION 0.3 FROM ubuntu # Install vnc, xvfb in order to create a 'fake' display and firefox RUN apt-get update && apt-get install -y x11vnc xvfb firefox RUN mkdir /.vnc # Setup a password RUN x11vnc -storepasswd 1234 ~/.vnc/passwd # Autostart firefox (might not be the best way, but it does the trick) RUN bash -c 'echo "firefox" >> /.bashrc' EXPOSE 5900 CMD ["x11vnc", "-forever", "-usepw", "-create"] # Multiple images example # # VERSION 0.1 FROM ubuntu RUN echo foo > bar # Will output something like ===> 907ad6c2736f FROM ubuntu RUN echo moo > oink # Will output something like ===> 695d7793cbe4 # You?ll now have two images, 907ad6c2736f with /bar, and 695d7793cbe4 with # /oink. de>
12.2. 指令
指令的一般格式为
FROM
格式为
第一条指令必须为
MAINTAINER
格式为
RUN
格式为
前者将在 shell 终端中运行命令,即
每条
CMD
支持三种格式
de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >CMD [“executable”,”param1″,”param2″] de> 使用 de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >exec de> 执行,推荐方式; de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >CMD command param1 param2 de> 在 de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >/bin/sh de> 中执行,提供给需要交互的应用; de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >CMD [“param1″,”param2”] de> 提供给 de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >ENTRYPOINT de> 的默认参数;
指定启动容器时执行的命令,每个 Dockerfile 只能有一条
如果用户启动容器时候指定了运行的命令,则会覆盖掉
EXPOSE
格式为
告诉 Docker 服务端容器暴露的端口号,供互联系统使用。在启动容器时需要通过 -P,Docker 主机会自动分配一个端口转发到指定的端口。
ENV
格式为
例如
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >ENV PG_MAJOR 9.3 ENV PG_VERSION 9.3.4 RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && … ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH de>
ADD
格式为
该命令将复制指定的
COPY
格式为
复制本地主机的
当使用本地目录为源目录时,推荐使用
ENTRYPOINT
两种格式:
de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >ENTRYPOINT [“executable”, “param1”, “param2”] de> de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >ENTRYPOINT command param1 param2 de>(shell中执行)。
配置容器启动后执行的命令,并且不可被
每个 Dockerfile 中只能有一个
VOLUME
格式为
创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。
USER
格式为
指定运行容器时的用户名或 UID,后续的
当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户,例如:
WORKDIR
格式为
为后续的
可以使用多个
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >WORKDIR /a WORKDIR b WORKDIR c RUN pwd de>
则最终路径为
ON BUILD
格式为
配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。
例如,Dockerfile 使用如下的内容创建了镜像
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >[...] ON BUILD ADD . /app/src ON BUILD RUN /usr/local/bin/python-build --dir /app/src [...] de>
如果基于 image-A 创建新的镜像时,新的Dockerfile中使用
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >FROM image-A #Automatically run the following ADD . /app/src RUN /usr/local/bin/python-build --dir /app/src de>
使用
12.3. 创建镜像
编写完成 Dockerfile 之后,可以通过
基本的格式为
要指定镜像的标签信息,可以通过
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker build -t myrepo/myapp /tmp/test1/ de>
13. 底层实现
Docker 底层的核心技术包括 Linux 上的名字空间(Namespaces)、控制组(Control groups)、Union 文件系统(Union file systems)和容器格式(Container format)。
我们知道,传统的虚拟机通过在宿主主机中运行 hypervisor 来模拟一整套完整的硬件环境提供给虚拟机的操作系统。虚拟机系统看到的环境是可限制的,也是彼此隔离的。 这种直接的做法实现了对资源最完整的封装,但很多时候往往意味着系统资源的浪费。 例如,以宿主机和虚拟机系统都为 Linux 系统为例,虚拟机中运行的应用其实可以利用宿主机系统中的运行环境。
我们知道,在操作系统中,包括内核、文件系统、网络、PID、UID、IPC、内存、硬盘、CPU 等等,所有的资源都是应用进程直接共享的。 要想实现虚拟化,除了要实现对内存、CPU、网络IO、硬盘IO、存储空间等的限制外,还要实现文件系统、网络、PID、UID、IPC等等的相互隔离。 前者相对容易实现一些,后者则需要宿主机系统的深入支持。
随着 Linux 系统对于名字空间功能的完善实现,程序员已经可以实现上面的所有需求,让某些进程在彼此隔离的名字空间中运行。大家虽然都共用一个内核和某些运行时环境(例如一些系统命令和系统库),但是彼此却看不到,都以为系统中只有自己的存在。这种机制就是容器(Container),利用名字空间来做权限的隔离控制,利用 cgroups 来做资源分配。
13.1. 基本架构
Docker 采用了 C/S架构,包括客户端和服务端。 Docker daemon 作为服务端接受来自客户的请求,并处理这些请求(创建、运行、分发容器)。 客户端和服务端既可以运行在一个机器上,也可通过 socket 或者 RESTful API 来进行通信。
Docker daemon 一般在宿主主机后台运行,等待接收来自客户端的消息。 Docker 客户端则为用户提供一系列可执行命令,用户用这些命令实现跟 Docker daemon 交互。
13.2. 名字空间
名字空间是 Linux 内核一个强大的特性。每个容器都有自己单独的名字空间,运行在其中的应用都像是在独立的操作系统中运行一样。名字空间保证了容器之间彼此互不影响。
pid 名字空间
不同用户的进程就是通过 pid 名字空间隔离开的,且不同名字空间中可以有相同 pid。所有的 LXC 进程在 Docker 中的父进程为Docker进程,每个 LXC 进程具有不同的名字空间。同时由于允许嵌套,因此可以很方便的实现嵌套的 Docker 容器。
net 名字空间
有了 pid 名字空间, 每个名字空间中的 pid 能够相互隔离,但是网络端口还是共享 host 的端口。网络隔离是通过 net 名字空间实现的, 每个 net 名字空间有独立的 网络设备, IP 地址, 路由表, /proc/net 目录。这样每个容器的网络就能隔离开来。Docker 默认采用 veth 的方式,将容器中的虚拟网卡同 host 上的一 个Docker 网桥 docker0 连接在一起。
ipc 名字空间
容器中进程交互还是采用了 Linux 常见的进程间交互方法(interprocess communication – IPC), 包括信号量、消息队列和共享内存等。然而同 VM 不同的是,容器的进程间交互实际上还是 host 上具有相同 pid 名字空间中的进程间交互,因此需要在 IPC 资源申请时加入名字空间信息,每个 IPC 资源有一个唯一的 32 位 id。
mnt 名字空间
类似 chroot,将一个进程放到一个特定的目录执行。mnt 名字空间允许不同名字空间的进程看到的文件结构不同,这样每个名字空间 中的进程所看到的文件目录就被隔离开了。同 chroot 不同,每个名字空间中的容器在 /proc/mounts 的信息只包含所在名字空间的 mount point。
uts 名字空间
UTS(“UNIX Time-sharing System”) 名字空间允许每个容器拥有独立的 hostname 和 domain name, 使其在网络上可以被视作一个独立的节点而非 主机上的一个进程。
user 名字空间
每个容器可以有不同的用户和组 id, 也就是说可以在容器内用容器内部的用户执行程序而非主机上的用户。
*注:关于 Linux 上的名字空间,这篇文章 介绍的很好。
13.3. 控制组
控制组(cgroups)是 Linux 内核的一个特性,主要用来对共享资源进行隔离、限制、审计等。只有能控制分配到容器的资源,才能避免当多个容器同时运行时的对系统资源的竞争。
控制组技术最早是由 Google 的程序员 2006 年起提出,Linux 内核自 2.6.24 开始支持。
控制组可以提供对容器的内存、CPU、磁盘 IO 等资源的限制和审计管理。
13.4. Union 文件系统
Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。
Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
另外,不同 Docker 容器就可以共享一些基础的文件系统层,同时再加上自己独有的改动层,大大提高了存储的效率。
Docker 中使用的 AUFS(AnotherUnionFS)就是一种 Union FS。 AUFS 支持为每一个成员目录(类似 Git 的分支)设定只读(readonly)、读写(readwrite)和写出(whiteout-able)权限, 同时 AUFS 里有一个类似分层的概念, 对只读权限的分支可以逻辑上进行增量地修改(不影响只读部分的)。
Docker 目前支持的 Union 文件系统种类包括 AUFS, btrfs, vfs 和 DeviceMapper。
13.5. 容器格式
最初,Docker 采用了 LXC 中的容器格式。自 1.20 版本开始,Docker 也开始支持新的 libcontainer 格式,并作为默认选项。
对更多容器格式的支持,还在进一步的发展中。
指令
指令的一般格式为
FROM
格式为
第一条指令必须为
MAINTAINER
格式为
RUN
格式为
前者将在 shell 终端中运行命令,即
每条
CMD
支持三种格式
de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >CMD [“executable”,”param1″,”param2″] de> 使用 de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >exec de> 执行,推荐方式; de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >CMD command param1 param2 de> 在 de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >/bin/sh de> 中执行,提供给需要交互的应用; de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >CMD [“param1″,”param2”] de> 提供给 de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >ENTRYPOINT de> 的默认参数;
指定启动容器时执行的命令,每个 Dockerfile 只能有一条
如果用户启动容器时候指定了运行的命令,则会覆盖掉
EXPOSE
格式为
告诉 Docker 服务端容器暴露的端口号,供互联系统使用。在启动容器时需要通过 -P,Docker 主机会自动分配一个端口转发到指定的端口。
ENV
格式为
例如
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >ENV PG_MAJOR 9.3 ENV PG_VERSION 9.3.4 RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && … ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH de>
ADD
格式为
该命令将复制指定的
COPY
格式为
复制本地主机的
当使用本地目录为源目录时,推荐使用
ENTRYPOINT
两种格式:
de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >ENTRYPOINT [“executable”, “param1”, “param2”] de> de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >ENTRYPOINT command param1 param2 de>(shell中执行)。
配置容器启动后执行的命令,并且不可被
每个 Dockerfile 中只能有一个
VOLUME
格式为
创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。
USER
格式为
指定运行容器时的用户名或 UID,后续的
当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户,例如:
WORKDIR
格式为
为后续的
可以使用多个
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >WORKDIR /a WORKDIR b WORKDIR c RUN pwd de>
则最终路径为
ON BUILD
格式为
配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。
例如,Dockerfile 使用如下的内容创建了镜像
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >[...] ON BUILD ADD . /app/src ON BUILD RUN /usr/local/bin/python-build --dir /app/src [...] de>
如果基于 image-A 创建新的镜像时,新的Dockerfile中使用
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >FROM image-A #Automatically run the following ADD . /app/src RUN /usr/local/bin/python-build --dir /app/src de>
使用
13.6 Docker 网络实现
Docker 的网络实现其实就是利用了 Linux 上的网络名字空间和虚拟网络设备(特别是 veth pair)。建议先熟悉了解这两部分的基本概念再阅读本章。
基本原理
首先,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)来收发数据包;此外,如果不同子网之间要进行通信,需要路由机制。
Docker 中的网络接口默认都是虚拟的接口。虚拟接口的优势之一是转发效率较高。 Linux 通过在内核中进行数据复制来实现虚拟接口之间的数据转发,发送接口的发送缓存中的数据包被直接复制到接收接口的接收缓存中。对于本地系统和容器内系统看来就像是一个正常的以太网卡,只是它不需要真正同外部网络设备通信,速度要快很多。
Docker 容器网络就利用了这项技术。它在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通(这样的一对接口叫做
创建网络参数
Docker 创建一个容器的时候,会执行如下操作:
- 创建一对虚拟接口,分别放到本地主机和新容器中;
- 本地主机一端桥接到默认的 docker0 或指定网桥上,并具有一个唯一的名字,如 veth65f9;
- 容器一端放到新容器中,并修改名字作为 eth0,这个接口只在容器的名字空间可见;
- 从网桥可用地址段中获取一个空闲地址分配给容器的 eth0,并配置默认路由到桥接网卡 veth65f9。
完成这些之后,容器就可以使用 eth0 虚拟网卡来连接其他容器和其他网络。
可以在
de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >–net=bridge de> 这个是默认值,连接到默认的网桥。 de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >–net=host de> 告诉 Docker 不要将容器网络放到隔离的名字空间中,即不要容器化容器内的网络。此时容器使用本地主机的网络,它拥有完全的本地主机接口访问权限。容器进程可以跟主机其它 root 进程一样可以打开低范围的端口,可以访问本地网络服务比如 D-bus,还可以让容器做一些影响整个主机系统的事情,比如重启主机。因此使用这个选项的时候要非常小心。如果进一步的使用 de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >–privileged=true de>,容器会被允许直接配置主机的网络堆栈。 de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >–net=container:NAME_or_ID de> 让 Docker 将新建容器的进程放到一个已存在容器的网络栈中,新容器进程有自己的文件系统、进程列表和资源限制,但会和已存在的容器共享 IP 地址和端口等网络资源,两者进程可以直接通过 de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >lo de> 环回接口通信。 de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >–net=none de> 让 Docker 将新容器放到隔离的网络栈中,但是不进行网络配置。之后,用户可以自己进行配置。
网络配置细节
用户使用
首先,启动一个
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run -i -t --rm --net=none base /bin/bash root@63f36fc01b5f:/# de>
在本地主机查找容器的进程 id,并为它创建网络命名空间。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker inspect -f '{{.State.Pid}}' 63f36fc01b5f 2778 $ pid=2778 $ sudo mkdir -p /var/run/netns $ sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid de>
检查桥接网卡的 IP 和子网掩码信息。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ ip addr show docker0 21: docker0: ... inet 172.17.42.1/16 scope global docker0 ... de>
创建一对 “veth pair” 接口 A 和 B,绑定 A 到网桥
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo ip link add A type veth peer name B $ sudo brctl addif docker0 A $ sudo ip link set A up de>
将B放到容器的网络命名空间,命名为 eth0,启动它并配置一个可用 IP(桥接网段)和默认网关。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo ip link set B netns $pid $ sudo ip netns exec $pid ip link set dev B name eth0 $ sudo ip netns exec $pid ip link set eth0 up $ sudo ip netns exec $pid ip addr add 172.17.42.99/16 dev eth0 $ sudo ip netns exec $pid ip route add default via 172.17.42.1 de>
以上,就是 Docker 配置网络的具体过程。
当容器结束后,Docker 会清空容器,容器内的 eth0 会随网络命名空间一起被清除,A 接口也被自动从
此外,用户可以使用
14. 附录一、Docker命令查询
基本语法
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >docker [OPTIONS] COMMAND [arg...] de>
一般来说,Docker 命令可以用来管理 daemon,或者通过 CLI 命令管理镜像和容器。可以通过
选项
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >-D=true|false 使用 debug 模式。默认为 false。 -H, --host=[unix:///var/run/docker.sock]: tcp://[host:port]来绑定或者 unix://[/path/to/socket] 来使用。 在 daemon 模式下绑定的 socket,通过一个或多个 tcp://host:port, unix:///path/to/socket, fd://* or fd://socketfd 来指定。 --api-enable-cors=true|false 在远端 API 中启用 CORS 头。缺省为 false。 -b="" 将容器挂载到一个已存在的网桥上。指定为 'none' 时则禁用容器的网络。 --bip="" 让动态创建的 docker0 采用给定的 CIDR 地址; 与 -b 选项互斥。 -d=true|false 使用 daemon 模式。缺省为 false。 --dns="" 让 Docker 使用给定的 DNS 服务器。 -g="" 指定 Docker 运行时的 root 路径。缺省为 /var/lib/docker。 --icc=true|false 启用容器间通信。默认为 true。 --ip="" 绑定端口时候的默认 IP 地址。缺省为 0.0.0.0。 --iptables=true|false 禁止 Docker 添加 iptables 规则。缺省为 true。 --mtu=VALUE 指定容器网络的 mtu。缺省为 1500。 -p="" 指定 daemon 的 PID 文件路径。缺省为 /var/run/docker.pid。 -s="" 强制 Docker 运行时使用给定的存储驱动。 -v=true|false 输出版本信息并退出。缺省值为 false。 --selinux-enabled=true|false 启用 SELinux 支持。缺省值为 false。SELinux 目前不支持 BTRFS 存储驱动。 de>
命令
Docker 的命令可以采用
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >docker-attach(1) 依附到一个正在运行的容器中。 docker-build(1) 从一个 Dockerfile 创建一个镜像 docker-commit(1) 从一个容器的修改中创建一个新的镜像 docker-cp(1) 从容器中复制文件到宿主系统中 docker-diff(1) 检查一个容器文件系统的修改 docker-events(1) 从服务端获取实时的事件 docker-export(1) 导出容器内容为一个 tar 包 docker-history(1) 显示一个镜像的历史 docker-images(1) 列出存在的镜像 docker-imp ort(1) 导入一个文件(典型为 tar 包)路径或目录来创建一个镜像 docker-info(1) 显示一些相关的系统信息 docker-inspect(1) 显示一个容器的底层具体信息。 docker-kill(1) 关闭一个运行中的容器 (包括进程和所有资源) docker-load(1) 从一个 tar 包中加载一个镜像 docker-login(1) 注册或登录到一个 Docker 的仓库服务器 docker-logout(1) 从 Docker 的仓库服务器登出 docker-logs(1) 获取容器的 log 信息 docker-pause(1) 暂停一个容器中的所有进程 docker-port(1) 查找一个 nat 到一个私有网口的公共口 docker-ps(1) 列出容器 docker-pull(1) 从一个Docker的仓库服务器下拉一个镜像或仓库 docker-push(1) 将一个镜像或者仓库推送到一个 Docker 的注册服务器 docker-restart(1) 重启一个运行中的容器 docker-rm(1) 删除给定的若干个容器 docker-rmi(1) 删除给定的若干个镜像 docker-run(1) 创建一个新容器,并在其中运行给定命令 docker-save(1) 保存一个镜像为 tar 包文件 docker-search(1) 在 Docker index 中搜索一个镜像 docker-start(1) 启动一个容器 docker-stop(1) 终止一个运行中的容器 docker-tag(1) 为一个镜像打标签 docker-top(1) 查看一个容器中的正在运行的进程信息 docker-unpause(1) 将一个容器内所有的进程从暂停状态中恢复 docker-version(1) 输出 Docker 的版本信息 docker-wait(1) 阻塞直到一个容器终止,然后输出它的退出符 de>
一张图总结 Docker 的命令
15. 附录二、常见仓库介绍
本章将介绍常见的一些仓库和镜像的功能,使用方法和生成它们的 Dockerfile 等。包括 Ubuntu、CentOS、MySQL、MongoDB、Redis、Nginx、Wordpress、Node.js 等。
15.1. Ubuntu
基本信息
Ubuntu 是流行的 Linux 发行版,其自带软件版本往往较新一些。 该仓库提供了 Ubuntu从12.04 ~ 14.10 各个版本的镜像。
使用方法
默认会启动一个最小化的 Ubuntu 环境。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run --name some-ubuntu -i -t ubuntu root@523c70904d54:/# de>
Dockerfile
15.2. CentOS
基本信息
CentOS 是流行的 Linux 发行版,其软件包大多跟 RedHat 系列保持一致。 该仓库提供了 CentOS 从 5 ~ 7 各个版本的镜像。
使用方法
默认会启动一个最小化的 CentOS 环境。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run --name some-centos -i -t centos bash bash-4.2# de>
Dockerfile
15.3. MySQL
基本信息
MySQL 是开源的关系数据库实现。 该仓库提供了 MySQL 各个版本的镜像,包括 5.6 系列、5.7 系列等。
使用方法
默认会在
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=mysecretpassword -d mysql de>
之后就可以使用其它应用来连接到该容器。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run --name some-app --link some-mysql:mysql -d application-that-uses-mysql de>
或者通过
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run -it --link some-mysql:mysql --rm mysql sh -c 'exec mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"$MYSQL_PORT_3306_TCP_PORT" -uroot -p"$MYSQL_ENV_MYSQL_ROOT_PASSWORD"' de>
Dockerfile
15.4. MongoDB
基本信息
MongoDB 是开源的 NoSQL 数据库实现。 该仓库提供了 MongoDB 2.2 ~ 2.7 各个版本的镜像。
使用方法
默认会在
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run --name some-mongo -d mongo de>
使用其他应用连接到容器,可以用
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run --name some-app --link some-mongo:mongo -d application-that-uses-mongo de>
或者通过
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run -it --link some-mongo:mongo --rm mongo sh -c 'exec mongo "$MONGO_PORT_27017_TCP_ADDR:$MONGO_PORT_27017_TCP_PORT/test"' de>
Dockerfile
15.5. Redis
基本信息
Redis 是开源的内存 Key-Value 数据库实现。 该仓库提供了 Redis 2.6 ~ 2.8.9 各个版本的镜像。
使用方法
默认会在
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run --name some-redis -d redis de>
另外还可以启用 持久存储。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run --name some-redis -d redis redis-server --appendonly yes de>
默认数据存储位置在
使用其他应用连接到容器,可以用
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run --name some-app --link some-redis:redis -d application-that-uses-redis de>
或者通过
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run -it --link some-redis:redis --rm redis sh -c 'exec redis-cli -h "$REDIS_PORT_6379_TCP_ADDR" -p "$REDIS_PORT_6379_TCP_PORT"' de>
Dockerfile
15.6. Nginx
基本信息
Nginx 是开源的高效的 Web 服务器实现,支持 HTTP、HTTPS、SMTP、POP3、IMAP 等协议。 该仓库提供了 Nginx 1.0 ~ 1.7 各个版本的镜像。
使用方法
下面的命令将作为一个静态页面服务器启动。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run --name some-nginx -v /some/content:/usr/share/nginx/html:ro -d nginx de>
用户也可以不使用这种映射方式,通过利用 Dockerfile 来直接将静态页面内容放到镜像中,内容为
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >FROM nginx COPY static-html-directory /usr/share/nginx/html de>
之后生成新的镜像,并启动一个容器。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker build -t some-content-nginx . $ sudo docker run --name some-nginx -d some-content-nginx de>
开放端口,并映射到本地的
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >sudo docker run --name some-nginx -d -p 8080:80 some-content-nginx de>
Nginx的默认配置文件路径为
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >docker run --name some-nginx -v /some/nginx.conf:/etc/nginx/nginx.conf:ro -d nginx de>
使用配置文件时,为了在容器中正常运行,需要保持
Dockerfile
15.7. WordPress
基本信息
WordPress 是开源的 Blog 和内容管理系统框架,它基于 PhP 和 MySQL。 该仓库提供了 WordPress 4.0 版本的镜像。
使用方法
启动容器需要 MySQL 的支持,默认端口为
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run --name some-wordpress --link some-mysql:mysql -d wordpress de>
启动 WordPress 容器时可以指定的一些环境参数包括
de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >-e WORDPRESS_DB_USER=… de> 缺省为 “root” de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >-e WORDPRESS_DB_PASSWORD=… de> 缺省为连接 mysql 容器的环境变量 de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >MYSQL_ROOT_PASSWORD de> 的值 de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >-e WORDPRESS_DB_NAME=… de> 缺省为 “wordpress” de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >-e WORDPRESS_AUTH_KEY=… de>, de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >-e WORDPRESS_SECURE_AUTH_KEY=… de>, de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >-e WORDPRESS_LOGGED_IN_KEY=… de>, de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >-e WORDPRESS_NONCE_KEY=… de>, de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >-e WORDPRESS_AUTH_SALT=… de>, de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >-e WORDPRESS_SECURE_AUTH_SALT=… de>, de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >-e WORDPRESS_LOGGED_IN_SALT=… de>, de style=”box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, ‘Liberation Mono’, Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(247, 247, 247);” >-e WORDPRESS_NONCE_SALT=… de> 缺省为随机 sha1 串
Dockerfile
15.8. Node.js
基本信息
Node.js是基于 JavaS
使用方法
在项目中创建一个 Dockerfile。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >FROM node:0.10-on build # replace this with your application's default port EXPOSE 8888 de>
然后创建镜像,并启动容器
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker build -t my-nodejs-app $ sudo docker run -it --rm --name my-running-app my-nodejs-app de>
也可以直接运行一个简单容器。
de style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; white-space: pre; border: 0px; display: inline; line-height: inherit; word-wrap: normal; background-color: transparent;" >$ sudo docker run -it --rm --name my-running-script -v "$(pwd)":/usr/src/myapp -w /usr/src/myapp node:0.10 node your-daemon-or-script.js de>
Dockerfile
16. 附录三、资源链接
- Docker 主站点: https://www.docker.io
- Docker 注册中心API: http://docs.docker.com/reference/api/registry_api/
- Docker Hub API: http://docs.docker.com/reference/api/docker-io_api/
- Docker 远端应用API: http://docs.docker.com/reference/api/docker_remote_api/
- Dockerfile 参考:https://docs.docker.com/reference/builder/
- Dockerfile 最佳实践:https://docs.docker.com/articles/dockerfile_best-practices/