深入浅出Docker


【编者的话】本文是一篇Docker入门文章,作者介绍了Docker相关的基础知识,包括Docker镜像、Dockerfile、Docker容器、Docker Hub。然后作者使用Docker搭建了一个WordPress应用,基础架构包含一个Nginx服务器来路由/代理请求、WordPress应用服务器来部署应用以及MySQL数据库来提供存储。初学Docker的同学可以看看。

在持续集成这样新的开发方法论流行的今天,软件工程师只是将代码推送出去并且祈祷代码能在另外的环境里成功运行的日子已经一去不复返了。开发、测试和运维之间的传统高墙正在逐渐瓦解,并且这些职责会互相渗透,从而造就了新型工程师。DevOps在业界流行,项目开发团队越来越敏捷高效,并且能够迅速响应变化。这样的转变使得新工具和框架随之兴起,帮助我们自动化地部署、测试和标准化基础架构。

转型浪潮的前端工具之一就是Docker,Docker是一个开放的平台,帮助开发人员和系统管理员构建、发布并运行分布式应用。在进一步深入探讨实际经验之前,推荐大家阅读这篇文章:《什么是Docker》

在开始操作之前,你需要先安装Docker,我在Mac上用Boot2Docker来安装,更为详细的适合你的平台的安装指南请参考Docker安装介绍。另外,可以使用云服务商来运行Docker主机,Digital Ocean提供运行在云端,并且可以使用Docker的服务器,只需要花费每小时0.007美元,要是你受限于带宽或资源的话,这是个很好的解决方法。

基础知识

Docker镜像

Docker镜像是一个只读容器,例如Ubuntu操作系统或者CentOS操作系统镜像。在Docker里运行的每个容器都需要基于某个Docker镜像。

Dockerfile

Dockerfile其实就是一些代码指令,它告诉Docker应该如何构建Docker镜像。Docker镜像是分层的,易于扩展,支持在已有的基础镜像上增加额外的功能。常用的基础镜像是ubuntu:latest,这是Ubuntu版本的基础镜像。

Docker容器

Docker容器可以看成是运行着Linux系统(通常精简过的Linux系统)的虚拟机的轻量级自包含实例,可以迅速启动和停止。Docker容器可以通过Docker镜像无限复制,它们是无状态/短暂的资源。

Docker Hub

Docker Hub给系统基础框架引入了软件工程DRY的原则,它是存储Dockerfile和镜像的全局仓库。目前Docker Hub已经有很多的可用镜像,比如Ubuntu、RedHat、RabbitMQ、MongoDB、Nginx。

深入Docker

让我们直接深入Docker,我们要构建一个简单的基础框架,其上运行一个WordPress的自包含实例,WordPress是被全世界很多公司和作家使用的流行博客工具。这个基础架构包含一个Nginx服务器来路由/代理请求,WordPress应用服务器来部署应用以及MySQL数据库来提供存储。最终的架构类似于:
dockercrashcourse.png

数据库容器

现在开始创建MySQL数据库容器,很幸运的是MySQL已经被Docker化了,我们可以从Docker Hub上直接下载,默认配置就很好,因此不需要写自己的Dockerfile或者构建新的镜像。可以使用docker run命令行来启动新容器。

第一次运行需要一些时间,因为需要下载镜像,下载一次之后就会缓存,后续的构建可以直接使用缓存。
docker run --name wordpress-db -e MYSQL_ROOT_PASSWORD=mysecretpassword -d mysql

上面的命令是让Docker使用MySQL基础镜像运行一个新容器,各个参数意义如下:
  • -name表示分配给新容器的名字(或者标签)
  • -e设置容器的环境变量,指定MySQL实例的密码,已有配置文档可以在MySQL Docker Hub中找到。
  • -d指定Docker在后台运行容器。
  • mysql指定要使用的Docker镜像的名字,这是从Docker Hub下载下来的。


注意:为了维护跨容器的数据,必须配置一个VOLUME来确保数据一致性。为了简单起见我们忽略了这个标志,但是要记住涉及状态的部署必须考虑到数据跨容器生命周期的持续性。

应用容器

下面我们需要运行WordPress应用容器,这个也已经被Docker化并放在Docker Hub上了:WordPress仓库
docker run --name wordpress-app --link wordpress-db:mysql -d wordpress

-link wordpress-db:mysql这个参数告诉Docker创建网络连接到wordpress-db容器(之前创建出来的),使得两个容器间能够网络通信。这个值分为两部分,左边部分指定想要连接的容器(wordpress-db),右边部分指定这个容器的主机别名(mysql)。

docker ps查看一下正在运行的容器:
docker ps

CONTAINER ID        IMAGE               COMMAND                CREATED              STATUS              PORTS               NAMES
c39600354fcb        wordpress:latest    "/entrypoint.sh apac   About a minute ago   Up About a minute   80/tcp              wordpress-app       
20e66802e914        mysql:latest        "/entrypoint.sh mysq   About a minute ago   Up About a minute   3306/tcp            wordpress-db       

可以看到有两个容器正在运行,一个在80端口,一个在3306端口。可以ssh进wordpress-app容器,验证可以连接到wordpress-db:
docker exec -i -t wordpress-app bash
ping mysql
64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.085 ms
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.127 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.108 ms

非常好,wordpress-app容器可以连接到wordpress-db容器。退出bash会话,如果需要也可以查看运行着的容器的日志。
docker logs wordpress-app

很好,一切看起来都不错。

Nginx容器

Web应用之前通常有HTTP Web代理。这样做有很多好处,比如控制请求路由、审查、安全、日志、缓存、负载均衡、存放静态内容等。Nginx是常用的HTTP Web代理服务器。因为需要创建自定义的Nginx,所以需要一个新Dockerfile来定义包含自定义Nginx配置的新镜像:
mkdir wordpress-nginx
cd wordpress-nginx
vi default.conf

server {
listen       80;
server_name  localhost;

error_log /var/log/nginx/error.log warn;

location / {
    proxy_pass http://wordpress-app:80/;
    proxy_redirect http://server_name http://wordpress-app:80/;
    proxy_set_header   Host               $host;
    proxy_set_header   X-Forwarded-For    $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto  http;
}

error_page   500 502 503 504  /50x.html;
location = /50x.html {
    root   /usr/share/nginx/html;
}
}

注意我们将到达的请求路由到80端口的wordpress-app容器。接下来创建Dockerfile,定义如何构建Nginx容器镜像:
vi Dockerfile

FROM nginx
COPY default.conf /etc/nginx/conf.d/default.conf

FROM nginx命令中的FROM指令告诉Docker从DockerHub上下载Nginx基础镜像
COPY default.conf /etc/nginx/conf.d/default.conf这个命令从当前目录得到default.conf,并拷贝到/etc/nginx/conf.d/下的容器镜像。

剩下的事情是构建新的Docker镜像并运行容器:
docker build -t wordpress-nginx .
docker run -d --name=wordpress-nginx --link=wordpress-app:wordpress-app -p 80:80 wordpress-nginx
docker ps

CONTAINER ID        IMAGE                    COMMAND                CREATED             STATUS              PORTS                         NAMES
2b9f99664249        wordpress-nginx:latest   "nginx -g 'daemon of   3 seconds ago       Up 2 seconds        443/tcp, 0.0.0.0:80->80/tcp   wordpress-nginx     
c39600354fcb        wordpress:latest         "/entrypoint.sh apac   9 minutes ago       Up 3 minutes        80/tcp                        wordpress-app       
20e66802e914        mysql:latest             "/entrypoint.sh mysq   9 minutes ago       Up 4 minutes        3306/tcp                      wordpress-db        

可能你会注意到我们指定了参数-p 80:80,这是告诉Docker暴露容器的80端口,这样可以从Docker的宿主机器外部访问该容器。

Hey Presto

在浏览器浏览http://DOCKER_HOST_IP/,看,WordPress已经可以用了,按照WordPress安装提示配置实例,很快就可以看到如下页面:
screen-shot-2015-01-31-at-23-02-51.png

总的来说,我们通过实际使用Docker Hub上的一些已有资源,学习到了一些Docker的基本概念,构建了WordPress的自包含可运行实例。一切只需要运行几个Docker命令。希望这篇文章能够帮助你开始Docker化你的应用基础架构,享受到Docker带来的巨大好处。

如果喜欢这篇文章,请帮忙转发给你的朋友,或者在Twitter,LinkedIn上共享。多谢阅读!

原文链接:A Dive into Docker(翻译:崔婧雯 校对:李颖杰)

===========================
译者介绍
崔婧雯,现就职于VMware,高级软件工程师,负责桌面虚拟化产品的质量保证工作。曾在IBM WebSphere业务流程管理软件担任多年系统测试工作。对虚拟化,中间件技术有浓厚的兴趣。

3 个评论

我去 这是情侣头像啊
哈,大脸猫
学习

要回复文章请先登录注册