使用DOCKER 部署 WEB 应用程序
在上一篇已经使用过docker run
,玩过 Docker 容器,也掌握了一些术语。掌握了以上这些知识,我们现在可以开始真正的工作,本文使用Docker 部署 Web 应用程序来说明如何部署。
静态站点
首先要看的是如何运行一个非常简单的静态网站。我们将从 Docker Hub 拉取一个 Docker 镜像,运行容器,看看如何运行 Web 服务器。
首先,我们将要使用的图像是一个单页网站,已经为演示的目创建好并托管在Docker Hub上prakhar1989/static-site
。 直接下载并运行镜像,使用docker run
. 如上所述,该 --rm
标志会在容器退出时自动移除容器。
$ docker run --rm prakhar1989/static-site
由于本地不存在该映像,因此客户端将首先从registry中获取该映像,然后运行该映像。如果一切顺利,应该会Nginx is running…在终端中看到一条消息。好的,现在服务器正在运行,如何查看网站?它在哪个端口上运行?更重要的是,如何直接从主机访问容器?按 Ctrl+C 停止容器。
那么,在这种情况下,客户端没有暴露任何端口,所以需要重新运行docker run
命令来发布端口。在此过程中,还应该找到一种方法,使终端不连接到正在运行的容器。这样,就可以愉快地关闭终端并保持容器运行。这称为分离模式。
$ docker run -d -P --name static-site prakhar1989/static-site
e61d12292d69556eabe2a44c16cbd54486b2527e2ce4f95438e504afb7b02810
在上面的命令中,-d
将分离我们的终端,-P
将所有暴露的端口发布到随机端口,最后--name
对应于我们想要给出的名称。现在们可以通过运行docker port [CONTAINER]
命令来查看端口
$ docker port static-site
80/tcp -> 0.0.0.0:32769
443/tcp -> 0.0.0.0:32768
您可以在浏览器中打开http://localhost:32769
注意:如果使用的是 docker-toolbox,那么可能需要使用docker-machine ip default来获取 IP。
此外,还可以指定客户端将连接转发到容器的自定义端口。
$ 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 镜像中运行网络服务器,您一定想知道 - 我如何创建自己的 Docker 镜像?在下一节探讨。
Docker 镜像
之前看过镜像,但在本节中,将更深入地了解 Docker 镜像是什么,并构建自己的镜像!最后,我们还将使用该映像在本地运行我们的应用程序。
Docker 镜像是容器的基础。在前面的示例中,从registry中提取了Busybox映像,并要求 Docker 客户端运行基于该映像的容器。要查看本地可用的图像列表,请使用该docker images
或者 docker image ls
命令。
$ 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是该镜像的相应的唯一标识符。
为简单起见,您可以想象一个类似于 git 存储库的镜像 -镜像可以随更改提交并具有多个版本。如果不提供特定版本号,则客户端默认为latest. 例如,可以拉取特定版本的ubuntu镜像
$ docker pull ubuntu:18.04
要获取新的 Docker 镜像,可以从注册表(例如 Docker Hub)获取它,也可以创建自己的镜像。Docker Hub上有数以万计的可用镜像。还可以使用命令行搜索镜像docker search
。
当涉及到镜像时,需要注意的一个重要区别是基础镜像和子镜像之间的区别。
-
基础镜像(base images)是没有父镜像的镜像,通常是使用 ubuntu、busybox 或 debian 等操作系统的镜像。
-
子镜像(child images)是建立在基础镜像上并添加附加功能的镜像。
然后是官方和用户镜像,它们可以是基本镜像和子镜像。
-
官方镜像是由 Docker 人员官方维护和支持的镜像。这些通常是一个字长。在上面的镜像列表中python,ubuntu、busybox和hello-world镜像是官方镜像。
-
用户镜像是由像你我这样的用户创建和共享的镜像。它们建立在基本镜像的基础上并添加了额外的功能。通常,这些格式为
user/image-name
.
自己的第一个镜像
现在对镜像有了更好的理解,是时候创建我们自己的镜像了。在本节中,目标是创建一个镜像来沙箱一个简单的Flask应用程序。出于本次研讨会的目的,我已经创建了一个有趣的小Flask 应用程序,.gif
每次加载时都会随机显示一只猫, 先在本地克隆存储库 -
$ git clone https://github.com/prakhar1989/docker-curriculum.git
$ cd docker-curriculum/flask-app
这应该在运行 docker 命令的机器上克隆,而不是在 docker 容器内。
现在下一步是使用此 Web 应用程序创建镜像。如上所述,所有用户镜像都基于基础镜像。由于我们的应用程序是用 Python 编写的,因此我们将使用的基本镜像将是Python 3。
Dockerfile
一个Dockerfile是包含命令的列表,该文件是客户在创建的镜像调用一个简单的文本文件。这是一种自动化镜像创建过程的简单方法。最好的部分是在 Dockerfile 中编写的命令几乎与它们等效的 Linux 命令相同。这意味着实际上不必学习新语法来创建自己的 dockerfile。
应用程序目录确实包含一个 Dockerfile,但由于我们是第一次这样做,我们将从头开始创建一个。首先,在我们最喜欢的文本编辑器中创建一个新的空白文件,并将其保存在与Flask 应用程序相同的文件夹中,名为Dockerfile.
我们从指定我们的基本镜像开始。使用FROM关键字来做到这一点 -
FROM python:3
下一步通常是编写复制文件和安装依赖项的命令。首先,设置一个工作目录,然后复制我们应用程序的所有文件。
# set a directory for the app
WORKDIR /usr/src/app
# copy all the files to the container
COPY . .
现在,我们有了文件,我们可以安装依赖项。
# install dependencies
RUN pip install --no-cache-dir -r requirements.txt
接下来需要指定的是需要公开的端口号。由于我们的 Flask 应用程序在 port 上运行5000,这就是我们将要指出的。
EXPOSE 5000
最后一步是编写运行应用程序的命令,简单来说就是 - python ./app.py
。我们使用CMD命令来做到这一点 -
CMD ["python", "./app.py"]
CMD是告诉容器它在启动时应该运行哪个命令。有了这个,我们Dockerfile现在准备好了。这是它的样子——
FROM python:3
# set a directory for the app
WORKDIR /usr/src/app
# copy all the files to the container
COPY . .
# install dependencies
RUN pip install --no-cache-dir -r requirements.txt
# define the port number the container should expose
EXPOSE 5000
# run the command
CMD ["python", "./app.py"]
现在有了Dockerfile,就可以建立自己的镜像。使用docker build
命令执行从Dockerfile.
下面的部分显示了运行相同的输出。在自己运行命令之前(不要忘记句号),请确保将我的用户名替换为您的用户名。此用户名应与您在Docker hub上注册时创建的用户名相同。如果您还没有这样做,请继续创建一个帐户。该docker build命令非常简单 - 它需要一个可选的标签名称,-t以及包含Dockerfile.
$ docker build -t yourusername/catnip .
Sending build context to Docker daemon 8.704 kB
Step 1 : FROM python:3
# 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镜像,客户端将首先拉取镜像,然后创建镜像。因此,运行该命令的输出看起来与本文不同。如果一切顺利,您的镜像应该准备好了!运行docker images
并查看您的镜像是否显示。
本节的最后一步是运行镜像,看看它是否真的有效(用你的用户名替换我的用户名)。
$ docker run -p 8888:5000 yourusername/catnip
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
刚刚运行的命令使用端口 5000 作为容器内的服务器,并将其暴露在端口 8888 上。转到端口 8888 的 URL,您的应用程序应该在那里运行。