恭喜你可以看到这里!我们前面学习了 docker run
以及 Docker 容器的知识,还有一些专业术语。有了这些知识,可以玩点新花样了,我们来使用 Docker 来部署一个 Web 应用!
接下来带你从零来运行一个简单的静态网站。我们将从 Docker Hub 中获取 Docker 镜像,运行容器并查看这个网站,非常容易。
我们要用的镜像是一个单页面的网页,我已经将这个镜像托管在 Docker 注册中心 - prakhar1989/static-site
。我们可以使用 docker run
直接下载并运行这个镜像。根据之前的描述,使用 --rm
选项会在容器退出时自动删除容器。
$ docker run --rm prakhar1989/static-site
由于本地没有这个镜像,所以客户端会先从注册中心拉取镜像,然后再运行。如果顺利的话,你会在终端看到 Nginx is running...
的一行输出。不过现在服务器已经运行了,我们如何访问网站呢?网站运行在哪个端口上?还有个问题,我如何从我的主机访问容器?先按下 Ctrl + C 停止容器。
在上面的这种情况下,客户端不会暴露任何端口,所以我们需要重新运行docker run
命令来设置端口。我们在操作的时候,应该有一种办法可以在关闭终端后也可以使得容器在运行,这种方式被称为 分离模式。
$ docker run -d -P --name static-site prakhar1989/static-sitee61d12292d69556eabe2a44c16cbd54486b2527e2ce4f95438e504afb7b02810
在上面的命令中,使用 -d
选项分离终端让容器在后台运行,-p
会设置端口,在这里会暴露一个随机的端口出来,最后使用 --name
来指定运行容器的名称。现在我们可以运行docker port [CONTAINER]
命令来查看端口
$ docker port static-site80/tcp -> 0.0.0.0:32769443/tcp -> 0.0.0.0:32768
你可以在浏览器中打开 http://localhost:32769 查看。
注意:如果您使用的是docker-toolbox,那么您可能需要使用它
docker-machine ip default
来获取IP。
注意:如果你使用的是 docker-toolbox,那么你可能需要使用 docker-machine ip default 来获取 IP。
还可以指定暴露一个特定的端口。
$ docker run -p 8888:80 prakhar1989/static-siteNginx is running...
要停止分离容器(后台运行),你可以使用 docker stop [容器ID]
,也可以使用 docker stop [容器名称]
来停止容器。
$ docker stop static-sitestatic-site
相信你也看到了这非常简单。在实际服务器上部署的话你只需要安装 Docker,然后运行上面的 Docker 命令。现在你已经了解了如何在 Docker 镜像中运行 Web 服务器,你一定想知道 - 如何创建自己的 Docker 镜像呢?我们在下面继续探讨这个问题。
在前面我们使用过镜像,下面将深入了解 Docker 镜像是什么以及如何构建自己的镜像!最后我们会使用自己的镜像在本地运行,然后将它部署在 AWS 上让别人可以访问。刺不刺激?来,跟我一起开始吧。
Docker 镜像是容器的基础。在前面的例子中,我们从注册中心中 拉取 了Busybox 镜像,并基于该镜像运行了容器。要查看本地可用的镜像列表,可以使用 docker images
命令。
$ docker imagesREPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZEprakhar1989/catnip latest c7ffb5626a50 2 hours ago 697.9 MBprakhar1989/static-site latest b270625a1631 21 hours ago 133.9 MBpython 3-onbuild cf4002b2c383 5 days ago 688.8 MBmartin/docker-cleanup-volumes latest b42990daaca2 7 weeks ago 22.14 MBubuntu latest e9ae3c220b23 7 weeks ago 187.9 MBbusybox latest c51f86c28340 9 weeks ago 1.109 MBhello-world latest 0a6ba66e537a 11 weeks ago 960 B
上面列出了我从注册中心拉取的镜像列表,以及我自己创建的镜像(马上你就会看到)。IMAGE ID
和 TAG
会构成一个镜像的唯一标识。
为了简单起见,你可以认为镜像类似于一个 Git 仓库,它可以 提交 和修改内容,也可以有多个版本。如果你没有指定版本,默认会认为是latest
。例如你可以拉取指定版本的 ubuntu
镜像。
$ docker pull ubuntu:12.04
想要获取最新的 Docker 镜像,可以从注册中心(比如 Docker Hub)获取,也可以自己创建镜像上传。Docker Hub 上有成千上万的镜像,你也可以在命令行使用 docker search
搜索镜像。
我们在谈镜像的时候有一个很重要的区别就是镜像和子镜像的差异:
基础镜像 是没有父镜像的镜像,比如像 ubuntu,busybox 或 debian 这种操作系统镜像。
子镜像 是基于基础镜像构建并添加其他功能的镜像。
然后是官方和用户镜像,它们也可以是基础镜像和子镜像。
官方镜像 是由 Docker 官方人员正式维护和支持的图像。在上面的镜像中,python
,ubuntu
,busybox
和hello-world
都是官方镜像。
用户镜像 是由你和我这样的用(xian)户(yu)创建和共享的镜像。它们基于基础镜像构建,然后会添加一些其他功能。一般用户镜像的格式为 user/image-name
。
现在你对镜像有了一个大致的理解,可以创建一个镜像了。我们的目标是创建一个沙盒化的 Flask 应用的镜像。为了达到我们这次的成果,我已经创建了一个有趣的 Flask 程序,每次加载的时候都会随机的显示一张猫咪的 gif
图片,哪个程序员还不喜欢猫呢?使用 git 克隆这个仓库,如下所示:
$ git clone https://github.com/prakhar1989/docker-curriculum$ cd docker-curriculum/flask-app
克隆操作在运行 docker 的计算机上,不是 docker 容器中。
下面我们使用这个程序来为它创建一个镜像。如上所述,所有用户镜像都要基于基础镜像。由于我们的应用程序是用 Python 编写的,我们要使用的基础镜像将是 Python 3。更具体地说,我们将使用 python:3-onbuild
这个版本的镜像。
可能你想问 onbuild
是什么鬼?
这些映像包含多个 ONBUILD 触发器,这是引导大多数应用所需的全部触发器。构建时会复制一个
requirements.txt
文件,在该文件处运行pip install
,然后将当前目录复制到/usr/src/app
。
换句话说,onbuild
版本包含自动使应用运行的部分,这些镜像将原本手动的操作自动化。这些镜像不会手动执行这些任务(或编写任务脚本),而是由你编写。我们现在拥有创建自己镜像的所有要素 - 一个功能强大的应用程序和一个基础镜像。接下来该怎么做?答案是 - 使用 Dockerfile。
一个 Dockerfile 是一个简单的文本文件,它包含 Docker 客户端在创建镜像时调用的命令列表。这是实现镜像创建过程自动化的一种简单方法。更重要的是,你在 Dockerfile 中编写的命令和 Linux 下几乎相同。意味着你你用学习新的语法来创建一个 dockerfile。
在你的应用程序中要包含一个 Dockerfile 文件,但由于我们第一次做,所以从头开始创建一个。首先使用你喜欢的编辑器在应用程序目录下创建一个名为 Dockerfile
的空白文件。
我们从指定基础镜像开始。使用FROM
关键字:
FROM python:3-onbuild
下一步通常是编写复制文件和安装依赖的命令。好在 onbuild
版本的镜像可以解决这个问题。下一步就是指定一个要暴露的端口号,由于我们的 Flask 应用在 5000
端口上运行,所以我们要加入一行指令暴露它。
EXPOSE 5000
最后一步是编写运行应用的命令,很简单只需要加入 python ./app.py
就可以了。我们使用 CMD 命令来实现:
CMD ["python", "./app.py"]
这里的 CMD
命令主要是告诉容器在启动时运行哪个命令。有了这个,我们的Dockerfile
就准备好了。这是它的样子
# our base imageFROM python:3-onbuild# specify the port number the container should exposeEXPOSE 5000# run the applicationCMD ["python", "./app.py"]
现在我们有了Dockerfile
,就可以创建我们的镜像了。使用 docker build
命令可以通过 Dockerfile
来构建一个镜像。
下面显示了运行构建后的输出。在你运行命令前(不要忘记 .
),请务必将用户名替换为你自己的。这里的用户名应该和你在 Docker Hub 中注册时是相同的。如果你还没有账户,请赶紧创建!docker build
命令非常简单,它可以通过 -t
指定标签的名称,最后的 .
代表一个路径,现在是当前目录。
$ docker build -t prakhar1989/catnip .Sending build context to Docker daemon 8.704 kBStep 1 : FROM python:3-onbuild# Executing 3 build triggers...Step 1 : COPY requirements.txt /usr/src/app/---> Using cacheStep 1 : RUN pip install --no-cache-dir -r requirements.txt---> Using cacheStep 1 : COPY . /usr/src/app---> 1d61f639ef9eRemoving intermediate container 4de6ddf5528cStep 2 : EXPOSE 5000---> Running in 12cfcf6d67ee---> f423c2f179d1Removing intermediate container 12cfcf6d67eeStep 3 : CMD python ./app.py---> Running in f01401a5ace9---> 13e87ed1fbc2Removing intermediate container f01401a5ace9Successfully 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
端口绑定。所以你可以访问 8888 端口查看应用:
恭喜!你已成功创建第一个 Docker 镜像。
现在这个应用程序没法给我的小伙伴们看,我要它有何用?所以在本节目中,我们将了解如何将这个🐂* 闪闪的程序部署到云端,以便可以和我的朋友分(zhuang)享(bi)!我们将使用AWS Elastic Beanstalk只需点击几下即可启动并运行我们的应用。我们还会看到使用 Beanstalk 让我们的应用程序更容易扩展和管理!
国内的小伙伴也可以在阿里云或 Vultr 以及其他的服务器主机上尝试哦!
在将我们的应用程序部署到 AWS 之前,需要做的第一件事是在 AWS 可以访问的注册中心上发布我们的镜像。你可以使用任何 Docker注册中心(甚至可以托管 自己的注册中心)。现在,让我们使用 Docker Hub 发布镜像。要发布只需输入
$ docker push prakhar1989/catnip
如果这是你第一次推送镜像,客户端会提示你登录一下,输入 Docker Hub 的账号和密码就可以了。
$ docker loginUsername: prakhar1989WARNING: login credentials saved in /Users/prakhar/.docker/config.jsonLogin Succeeded
请记住将上面的登录名换成你自己的。镜像的格式应该以 username/image_name
发布,这个位置非常重要。
完成后,你可以在 Docker Hub 上查看镜像。例如,这是我的镜像 网址。
注意:在我们继续之前,我想澄清的一件事是,为了部署到 AWS,在公共注册中心(或任何注册中心)上放置镜像并不是必须的。如果你在为下一个百万融资的独角兽公司写代码,当我没说。我们之所以公开推送镜像,是因为它跳过了一些中间配置步骤,让部署变得更简单。
现在你的镜像已经在线了,任何安装了 Docker 的人都可以通过输入 run
来把玩你的应用。
$ docker run -p 8888:5000 prakhar1989/catnip
摸摸自己的头再想想你之前是怎么部署程序的,就知道头发是怎么消失的!
AWS Elastic Beanstalk(EB)是 AWS 提供的 PaaS(平台即服务)。如果你用过 Heroku、Google App Engine,你会很快熟悉它。作为开发人员,你只需告诉 EB 如何运行你的应用程序,它将负责其余的工作 - 包括扩展,监控甚至更新。2014 年 4 月,EB 增加了对运行单容器部署的支持,这是我们用来部署应用程序的方法。虽然 EB 具有非常直观的 CLI,但还需要做一些配置,为了简单起见,我们将使用 Web UI 启动应用程序。
要继续,你需要一个有余额的 AWS 账户。如果还没有,请使用信用卡填写相关信息。但不用担心,它是免费的,我们在本教程中所做的任何事情也都是免费的!让我们开始吧。
以下是步骤:
登录AWS 控制台。
单击 Elastic Beanstalk。在左上角的计算部分,或者访问 Elastic Beanstalk 控制台。
单击右上角的 “创建新应用程序”
为你的应用程序提供一个吊炸天(但唯一)的名称,并提供(可选)描述
在“ 新建环境” 中,创建一个新环境并选择 “Web服务器环境”。
通过选择域来填写环境信息。这个 URL 是你给朋友分享的内容,请确保它易于记忆。
在基本配置部分。从预定义平台中选择 Docker。
现在我们需要上传我们的应用代码。但是由于我们的应用程序打包在 Docker 容器中,我们只是告诉 EB 我们的 contianer。打开 flask-app
文件夹中的 Dockerrun.aws.json
文件,然后根据镜像的名称编辑镜像。先别急,我马上解释一下这个文件的内容。完成后,单击单选按钮 “上传你自己的” 并选择这个文件。
你看到的最终界面会有一些微调器提示你的环境正在设置中。首次安装通常需要大约 5 分钟。
在我们等待的时候,来快速查看Dockerrun.aws.json
文件包含的内容。此文件基本上是 AWS 特定文件,它告诉 EB 有关我们的应用程序和 docker 配置的详细信息。
{"AWSEBDockerrunVersion": "1","Image": {"Name": "prakhar1989/catnip","Update": "true"},"Ports": [{"ContainerPort": "5000"}],"Logging": "/var/log/nginx"}
这个文件一看就懂,你也可以 参考 官方文档获取更多信息。我们提供给 EB 应该使用的镜像名称以及容器应该打开的端口。
希望到现在为止,我们的实例应该准备好了。转到 EB 页面,你应该有一个绿色打勾,表示你的应用程序是存活的。
继续在浏览器中打开 URL,你应该看到应用程序的样子。接下来打开你的 QQ、微信、Telegram 把这个链接发送给你的基佬们,让他们也享受一下可爱的猫咪。
恭喜!你已经部署了第一个 Docker 应用!看起来好像有很多步骤,但使用 EB 的 命令行工具,只要通过几次点击就可以模仿 Heroku 的功能!希望你会同意 Docker 消除了在云端构建和部署应用程序的许多痛苦。我建议你阅读单容器环境中的AWS 文档,以了解存在哪些功能。
在本教程的下一部分(也是最后一部分),我们将稍微提高一点,部署一个接近实际的应用程序; 具有持久后端存储层的应用程序。让我们马上开始吧!