原文见: docker-curriculum.com/#docker-com… 最近在看Docker的相关知识,在耗子叔专栏的推荐下,阅读了Docker for Beginners ,先将其翻译出来,方便大家学习。 跟作者联系过了,已经取得了作者的同意。
1. 在Docker中部署Web应用
在上篇文章中,我们已经学习了docker run以及一些Docker 领域的相关术语。接下来我们将继续学习如何在生产环境中使用Docker。比如用Docker部署一个静态网站。
1.1 静态网站
首先我们演示如何运行一个静态网站。我们准备从Docker Hub中获取镜像,运行容器,展示如何轻松的运行一个web服务器。 让我们开始吧,我们用到的镜像来自于我之前在Docker注册中心生成的,prakhar1989/static-site。我们先下载然后使用docker run 运行。
$ docker run --rm prakhar1989/static-site
复制代码
--rm 表示如果镜像存在的话,自动删除。 因为本地不存在该镜像,因此Docker客户端首先会从注册中心获取镜像,然后运行。一切正常的话,你将会在终端中看到 Ngnix is running...。
现在服务跑起来了,那么问题来了。怎么才能访问网站呢?网站运行在哪个端口上?我们怎么才能在主机上直接访问容器呢?先按下Ctrl+C,停止容器。
这个例子中,客户端没有暴露任何端口,我们需要再次运行docker run 来发布端口号。
我们应该寻找这样一种方式,关掉终端后,容器依然在运行,这就叫做分离模式。
$ docker run -d -P --name static-site prakhar1989/static-site
e61d12292d69556eabe2a44c16cbd54486b2527e2ce4f95438e504afb7b02810
复制代码
-d 将会分离我们的终端,-P表示给待发布的端口一个随机的端口号,--name 表示容器的命名。现在我们可以使用docker port [容器的名字]来查看正在运行的端口号。
$ docker port static-site
80/tcp -> 0.0.0.0:32769
443/tcp -> 0.0.0.0:32768
复制代码
现在你就可以在浏览器中打开 http://localhost:32769(根据每个人运行的状况不同,端口号可能需要更改)。 你也可以指定一个端口,用于客户端与容器建立连接。
$ docker run -p 8888:80 prakhar1989/static-site
Nginx is running...
复制代码
使用docker stop 并且指定容器Id,关闭容器。在这个例子中,我们也可以使用static-site 这个名字来关闭容器。
$ docker stop static-site
static-site
复制代码
我相信你肯定会认同,整个过程是如此的简单。要在真实的服务器上部署这个,你仅仅需要安装Docker,然后运行上述的Docker命令。现在你已经学到了如何在Docker镜像中运行一个web服务。你肯定也想知道,如何生成一个自己的Docker镜像,我们将在下一节解答这个问题。
1.2 Docker 镜像
在深入了解镜像之前,这一节我们先深入学习Docker镜像是什么以及如何构建我们自己的镜像。最后,我们会使用这个镜像来在本地运行我们的应用,最终在AWS上发布,和我们的朋友分享。听起来是不是激动人心呢,让我们动起来。
Docker镜像是容器的基础,在前面的例子中,我们从注册中心拿到了Busybox的镜像,然后用Docker客户端在镜像的基础上运行容器。我们使用docker images 命令来查看本地有哪些可用的Docker镜像。
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
prakhar1989/catnip latest c7ffb5626a50 2 hours ago 697.9 MB
prakhar1989/static-site latest b270625a1631 21 hours ago 133.9 MB
python 3-onbuild cf4002b2c383 5 days ago 688.8 MB
martin/docker-cleanup-volumes latest b42990daaca2 7 weeks ago 22.14 MB
ubuntu latest e9ae3c220b23 7 weeks ago 187.9 MB
busybox latest c51f86c28340 9 weeks ago 1.109 MB
hello-world latest 0a6ba66e537a 11 weeks ago 960 B
复制代码
上面列出了我从注册中心拿到的镜像和自己创建的镜像。TAG表示镜像的快照,IMAGE ID 是镜像的唯一标示。 你可以把镜像想像成有不同版本,如果不指定版本好的话,Docker客户端默认拿最新版本 latest。例如你也可以获取指定版本号的Ubuntu。
$ docker pull ubuntu:12.04
复制代码
镜像分为基础镜像和子镜像。
- 基础镜像 是没有父镜像的镜像,通常是类似操作系统的镜像。例如 ubuntu,busybox,debian
- 子镜像 是在基础镜像上添加的额外的功能。 镜像又可以分为用户镜像和官方镜像。
- 官方镜像 是官方提供的镜像。上面用到的python,ubuntu,busybox以及hello-world都是官方镜像。
- 用户镜像 是用户生成分享的镜像。用户在基础镜像的基础上添加功能,通常以user/image-name的形式命名。
1.3 我们的第一个镜像
现在我们对镜像有了进一步的了解,是时候创建我们自己的镜像了。我们在这节的目标是创建一个包含Flask应用的镜像。我已经创建了一个用于展示猫的动图的应用。
$ git clone https://github.com/prakhar1989/docker-curriculum
$ cd docker-curriculum/flask-app
复制代码
下一步就是在创建一个包含这个应用的镜像,像之前提到的那样,所用用户镜像需要一个基础镜像。我们用到的将会是Python 3。更确切的说,我们会用到 python:3-onbuild版本的python镜像。 那什么是onbuild版本呢? onbuild 版本包含自动使应用运行的部分。这些镜像将原本手动的操作自动化。现在我们有了创建镜像的依赖。那我们要怎么创建镜像呢?答案是Dockefile。
1.4 Dockfile
Dockerfile 是一个简单文档,包含了一系列的Docker 客户端构建镜像用到的命令。Dockerfile跟Linux命令类似,这意味着你不需要额外学习Docker语法。我们在flask app 的同目录下创建一个名字为Dockerfile的文档。 我们使用FROM 关键字来指定我们的基础镜像。
FROM python:3-onbuild
复制代码
下一步是写命令复制文件和安装依赖。幸运的是,onbuild版本的镜像将会完成这些。接下来,我们需要指定暴露的端口号。我们的flask应用运行在5000 端口上。
EXPOSE 5000
复制代码
最后一步是编写命令让应用运行起来。我们使用CMD命令来完成这个。
CMD ["python", "./app.py"]
复制代码
CMD的主要作用是告诉容器运行起来要执行的命令。现在我们的Dockerfile已经准备好了。
# our base image
FROM python:3-onbuild
# specify the port number the container should expose
EXPOSE 5000
# run the application
CMD ["python", "./app.py"]
复制代码
下面将会展示运行之后的输出,在运行这些命令之前,请确保已经替换了自己的用户名。用户名应该和你在Docker hub中注册的一样。如果你还没有的话,那么注册一个吧。Docker build命令非常简单, -t表示标签名称,以及Dockerfile的路径。
$ docker build -t prakhar1989/catnip .
Sending build context to Docker daemon 8.704 kB
Step 1 : FROM python:3-onbuild
# Executing 3 build triggers...
Step 1 : COPY requirements.txt /usr/src/app/
---> Using cache
Step 1 : RUN pip install --no-cache-dir -r requirements.txt
---> Using cache
Step 1 : COPY . /usr/src/app
---> 1d61f639ef9e
Removing intermediate container 4de6ddf5528c
Step 2 : EXPOSE 5000
---> Running in 12cfcf6d67ee
---> f423c2f179d1
Removing intermediate container 12cfcf6d67ee
Step 3 : CMD python ./app.py
---> Running in f01401a5ace9
---> 13e87ed1fbc2
Removing intermediate container f01401a5ace9
Successfully built 13e87ed1fbc2
复制代码
如果你没有python:3-onbuild镜像的话,客户端首先会拉取镜像,然后生成你自己的镜像。因此你运行之后的输出可能会和上面稍有不同。小心点,你将会正确的运行它。现在你的镜像已经生成了,使用docker images 命令来查看你的镜像吧。 最后一步就是让你的镜像跑起来,看它是否正确运行。
$ docker run -p 8888:5000 prakhar1989/catnip
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
复制代码
我们在容器内部使用5000端口,并把它暴露在外部的8888端口上,访问URL的8888端口,你的应用就会像下面这样。