跳转至

第1章 Docker入门

1.11 在docker中运行Hello World

1.11.1 问题

你已经拥有一台Docker主机,想运行你的第一个容器。你想学习容器的不同生命周期。比如,你想运行一个容器并在其中打印hello world。

1.11.2 解决方案

你已经见过了

1
$ docker ps

命令,该命令用于列出所有运行中的容器。

首先,你想启动一个容器。让我们立即开始,执行docker run命令,如下所示。

1
$ docker run busybox echo hello world

容器来源于镜像。docker run命令与需要一个参数来指定使用哪个镜像。

1.11.3 讨论

如果列出运行中的容器,你会发现没有容器正在运行。这是因为容器一旦完成了它的工作(输出hello world),就停止了。但是容器并没有完全消失,你可以通过

1
$ docker ps -a

命令看到这个容器。

你可以通过

1
$ docker rm 8f7089b187e8

命令将这个容器永久删除。该容器使用的镜像已经被下载到了本地,

1
$ docker image

命令将会输出这个镜像的信息。

如果任何运行中或者已经停止的容器都没有使用这个镜像,你就可以通过

1
$ docker rmi busybox

命令来删除这个镜像。

运行echo命令虽然很有趣,但是获得一个终端会话会更好。要想在容器中运行/bin/bash,你需要使用-t-i参数来获得一个交互式会话,下面以使用Ubuntu镜像为例进行说明。

1
$ docker run -t -i ubuntu:14.04 /bin/bash

你会看到Docker下载的ubuntu:14.04镜像由多个层组成,然后你得到了一个容器中root权限的会话。提示符也显示了这个容器的ID。一旦你推出这个终端,该容器就会停止运行,就像我们前面的hello world例子一样。

1.12 以后台方式运行docker容器

1.12.1 问题

你已经知道如何以交互方式启动一个容器,但是你想以后台方式运行一个服务。

1.12.2 解决方案

使用docker run-d选项。

运行下面的命令,将会在容器中启动一个简单的基于Python的HTTP服务器。

1
$ docker run -d -p 1234:1234 python:2.7 python -m SimpleHTTPServer 1234

1.12.3 讨论

这个-d参数会让容器在后台运行。你可以通过运行exec命令来启动一个bash shell,再次进入到该容器中,如下所示。

1
$ docker exec -ti 9d7cebd75dcf /bin/bash

在官方文档(https://docs.docker.com/reference/run/)[^1]中还有docker run的其他很多选项。

[^1] 原文如此,现在应该是https://docs.docker.com/engine/reference/commandline/run/

1.13 创建、启动、停止和移除容器

1.13.1 问题

你已经知道如何启动一个容器并让它在后台运行。你希望学习基本命令来管理容器的整个生命周期。

1.13.2 解决方案

使用 Docker 命令行的createstartstopkillrm命令。你可以在这些命令后面加上-h或者——h选项来查看它们的使用方法,或者只输入命令而不指定任何参数(比如docker create)。

1.13.3 讨论

在范例 1.12 中,你通过docker run自动启动了一个容器。你也可以通过docker create命令来创建一个容器。继续使用上面简单的HTTP服务器的例子,唯一的区别就是这里没有指定-d选项。当创建容器之后,你需要运行docker start来启动这个容器,如下所示。

1
2
3
4
$ docker create -P ——expose=1234 python:2.7 python -m SimpleHTTPServer 1234
$ docker ps -a
$ docker start a842945e2414
$ docker ps

要想停止一个正在运行中的容器,可以选择使用docker kill(这个命令会发送SIGKILL信号到容器)或者docker stop(这个命令会发送SIGTERM到容器,如果在一定时间内容器还没有停止,则会再发送SIGKILL信号强制停止)。这两个命令最终的结果是停止容器的运行,该容器将不会出现在docker ps返回的运行中容器列表中。但是,容器还没有完全消失(比如容器的文件系统还在)。你可以通过docker restart来重启这个容器,或者通过docker rm移除这个容器,如下所示。

1
2
3
4
5
$ docker restart a842945e2414
$ docker ps
$ docker kill a842945e2414
$ docker rm a842945e2414
$ docker ps -a

如果你有很多停止中的容器待删除,可以在一条命令中使用嵌套的 shell 来删除所有容器。docker ps-q选项只会返回容器的 ID 信息,如下所示。

1
$ docker rm $(docker ps -a -q)

1.14 使用Dockerfile构建Docker镜像

1.14.1 问题

你知道了如何从公有的Docker registry下载镜像,但是你想构建自己的Docker镜像。

1.14.2 解决方案

使用Dockerfile构建镜像。Dockerfile是一个文本文件,它记述了Docker构建一个镜像所需要的过程,包括安装软件包、创建文件夹、定义环境变量以及其他一些操作。在第2章中我们会对Dockerfile和构建镜像做更深入的说明。本范例中只会涉及构建镜像的基本概念。

作为一个简单例子,我们假设你要基于 busybox 镜像创建一个新镜像,并定义一个环境变量。busybox 镜像是一个包含了 busybox(http://www.busybox.net/about.html)二进制文件的 Docker 镜像,这个二进制文件将很多 Unix 实用工具打包到了一个单一的二进制文件中。在一个空文件夹下创建一个名为 Dockerfile 的文件,如下所示。

1
2
FROM busybox
ENV foo=bar

可以通过docker build命令来构建一个新镜像,并命名为busybox2,如下所示。

1
$ docker build -t busybox2 .

构建结束之后,你就能通过docker images命令看到新构建的镜像了。可以基于这个新镜像启动一个容器,检查一下其中是否有一个名为foo的环境变量,并且其值被设置为了bar,如下所示。

1
2
$ docker images
$ docker run busybox2 env | grep foo

1.14.3 参考

Dockerfile 参考指南(https://docs.docker.com/reference/builder/)[^1]

第 2 章,其中会对创建镜像和共享镜像进行说明

[^1] 现在是https://docs.docker.com/engine/reference/builder/

1.15 在单一容器中使用Supervisor运行WordPress

1.15.1 问题

你已经知道了如何将两个容器链接到一起(参见范例1.16),不过你希望在一个容器中运行应用程序所需的所有服务。以运行WordPress为例,你想在一个容器中同时运行MySQL和HTTPD服务。由于Docker运行的是前台进程,所以你需要找到一种同时运行多个“前台”进程的方式。

1.15.2 解决方案

使用Supervisor(http://supervisord.org/index.html)来监控并运行MySQL和HTTPD。Supervisor不是一个init系统,而是一个用来控制多个进程的普通程序。

本范例是一个在容器中使用Supervisor同时运行多个进程的例子。你可以以此为基础在一个Docker镜像中运行多个服务(比如SSH、Nginx)。本范例中,WordPress的配置是一个最精简的可行配置,并不适用于生产环境。

示例中的文件可以在GitHub(https://github.com/how2dock/docbook/tree/master/ch01/supervisor)下载。这些文件中包括一个用于启动虚拟机的Vagrantfile,Docker运行在该虚拟机中,还包含一个Dockerfile来定义要创建的镜像,此外还有一个Supervisor的配置文件(supervisord.conf)和一个WordPress的配置文件(wp-config.php)。

如果你不想使用Vagrant,也可以使用其中的Dockerfile、supervisord和WordPress的配置文件,在自己的Docker主机上来安装。

为了运行WordPress,你需要安装MySQL、Apache 2(即httpd)、PHP以及最新版本的WordPress。你将需要创建一个用于WordPress的数据库。在该范例的配置文件中,WordPress数据库用户名为root,密码也是root,数据库名为wordpress。如果你想对数据库的配置进行修改,需要同时修改wp-config.php和Dockerfile这两个文件,并让它们的设置保持一致。

Dockerfile文件用来描述一个Docker镜像是如何构建的,后面章节会有关于Dockerfile的详细说明。如果这是你第一次使用Dockerfile文件,那么你可以直接使用下面的文件,以后再学习Dockerfile(参见范例2.3对Dockerfile的介绍)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
FROM ubuntu:14.04
RUN apt-get update && apt-get -y install \
  apache2 \
  php5 \
  php5-mysql \
  supervisor \
  wget
RUN echo 'mysql-server mysql-server/root_password password root' | \
  debconf-set-selections && \
  echo 'mysql-server mysql-server/root_password_again password root' | \
  debconf-set-selections
RUN apt-get install -qqy mysql-server
RUN wget http://wordpress.org/latest.tar.gz && \
  tar xzvf latest.tar.gz && \
  cp -R ./wordpress/* /var/www/html && \
  rm /var/www/html/index.html
RUN (/usr/bin/mysqld_safe &); sleep 5; mysqladmin -u root -proot create wordpress
COPY wp-config.php /var/www/html/wp-config.php
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
EXPOSE 80
CMD ["/usr/bin/supervisord"]

Supervisor的配置文件supervisord.conf如下所示。

1
2
3
4
5
6
7
8
9
[supervisord]
nodaemon=true
[program:mysqld]
command=/usr/bin/mysqld_safe
autostart=true
autorestart=true
user=root
[program:httpd]
command=/bin/bash -c "rm -rf /run/httpd/* && /usr/sbin/apachectl -D FOREGROUND"

这里定义了两个被监控和运行的服务:mysqld和httpd。每个程序都可以使用诸如autorestart和autostart等选项。最重要的指令是command,其定义了如何运行每个程序。在这个例子中,Docker容器只需要运行一个前台进程:supervisord。从Dockerfile中的CMD ["/usr/bin/supervisord"]这一行也能看出来。

在你的Docker主机上,构建该镜像并启动一个后台容器。如果按照例子中的配置文件使用了基于Vagrant的虚拟机,可以执行如下命令。

1
2
3
$ cd /vagrant
$ docker build -t wordpress .
$ docker run -d -p 80:80 wordpress

容器启动后还会在宿主机和Docker容器之间为80端口进行端口映射。现在只需要在浏览器中打开http://<ipofdocker_host>,就可以进入到WordPress的配置页面了。

1.15.3 讨论

尽管通过Supervisor在一个容器内同时运行多个应用服务工作起来非常完美,但是你最好还是使用多个容器来运行不同的服务。这能充分利用容器的隔离优势,也能帮助你创建基于微服务设计思想的应用(参见《微服务设计》)。最终这也将会使你的应用更具弹性和可扩展性。

1.15.4 参考

Supervisor 文档(http://supervisord.org/index.html

Docker Supervisor 文档(https://docs.docker.com/articles/using_supervisord/

1.16 使用两个链接在一起的容器运行 WordPress 博客程序

1.16.1 问题

你希望通过容器来运行一个WordPress网站(http://wordpress.com/),但是你不想让MySQL和WordPress在同一个容器中运行。你时刻谨记对关注点进行分离的原则,并尽可能地对应用程序的不同组件进行解耦。

1.16.2 解决方案

启动两个容器:一个运行来自Docker Hub(http://hub.docker.com/)的官方WordPress,另一个运行MySQL数据库。这两个容器通过Docker命令行工具的——link选项链接在一起。

开始下载最新的WordPress(https://hub.docker.com/_/wordpress)和MySQL(https://hub.docker.com/_/mysql/)镜像,如下所示。

1
2
3
$ docker pull wordpress:latest
$ docker pull mysql:latest
$ docker images

评论