第2部分:容器 | Part 2: Containers

开始,第2部分:容器

  • 1:概况介绍

  • 2:集装箱

  • 3:服务

  • 4:成群

  • 5:堆叠

  • 6:部署应用程序

先决条件

  • 安装Docker版本1.13或更高版本...

  • 阅读第1部分中的方向。

  • 给您的环境一个快速测试运行,以确保您已经设置好了:

码头经营哈罗-世界

导言

现在是开始以Docker方式构建应用程序的时候了。我们将从这种应用程序的层次结构的底部开始,该应用程序是一个容器,我们将在此页面上进行介绍。在这个层次上面是一个服务,它定义了容器在生产中的行为方式,在第3部分中进行了讨论。最后,在顶层是堆栈,定义了第5部分中介绍的所有服务的交互。

  • 堆叠

  • 服务

  • 集装箱你在这里

您的新开发环境

在过去,如果您要开始编写Python应用程序,您的首要任务就是将Python运行时安装到您的计算机上。但是,这就造成了这样一种情况:为了使应用程序按预期运行,计算机上的环境必须是这样的;运行应用程序的服务器也是如此。

使用Docker,您只需获取一个可移植的Python运行时作为映像,无需安装。然后,您的构建可以将基本Python映像与应用程序代码放在一起,确保应用程序、其依赖项和运行时都能一起运行。

这些便携式图像是由称为a的东西定义的Dockerfile

使用Dockerfile

Dockerfile将定义容器内环境中发生的事情。在这个环境中,对网络接口和磁盘驱动器等资源的访问是虚拟化的,这与系统的其他部分是隔离的,因此您必须将端口映射到外部世界,并具体说明要将哪些文件“复制”到该环境。但是,在这样做之后,您可以预期您的应用程序的构建是在Dockerfile无论在哪里运行都会表现得完全一样。

Dockerfile

创建一个空目录。将目录(cd)更改为新目录,创建一个名为的文件Dockerfile,将以下内容复制并粘贴到该文件中并保存。注意解释新Dockerfile中每条语句的注释。

# Use an official Python runtime as a parent image FROM python:2.7-slim # Set the working directory to /app WORKDIR /app # Copy the current directory contents into the container at /app ADD . /app # Install any needed packages specified in requirements.txt RUN pip install -r requirements.txt # Make port 80 available to the world outside this container EXPOSE 80 # Define environment variable ENV NAME World # Run app.py when the container launches CMD ["python", "app.py"]

Dockerfile指我们还没有创建的几个文件,即app.pyrequirements.txt让我们创造下一个。

应用程序本身

再创建两个文件,requirements.txtapp.py,并将它们放在同一个文件夹中,Dockerfile这就完成了我们的应用程序,正如您所看到的,这个应用程序非常简单。当以上Dockerfile被塑造成一幅图像,app.pyrequirements.txt会因为这个而出现DockerfileADD命令的输出。app.py可以通过HTTP访问,这要感谢EXPOSE命令。

requirements.txt

Flask Redis

app.py

from flask import Flask from redis import Redis, RedisError import os import socket # Connect to Redis redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2) app = Flask(__name__) @app.route("/") def hello(): try: visits = redis.incr("counter") except RedisError: visits = "<i>cannot connect to Redis, counter disabled</i>" html = "<h3>Hello {name}!</h3>" \ "<b>Hostname:</b> {hostname}<br/>" \ "<b>Visits:</b> {visits}" return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits) if __name__ == "__main__": app.run(host='0.0.0.0', port=80)

现在我们看到了pip install -r requirements.txt安装用于Python的Flask和Redis库,应用程序打印环境变量NAME,以及调用的输出socket.gethostname()最后,由于Redis没有运行%28,我们只安装了Python库,而没有安装Redis本身的%29,因此我们应该期望在这里使用它的尝试会失败并产生错误消息。

:在容器中检索容器ID时访问主机的名称,这就像正在运行的可执行文件的进程ID一样。

而已!您requirements.txt的系统中不需要Python或其他任何东西,也不会在您的系统上安装或运行此映像。看起来你并没有真正用Python和Flask建立一个环境,但是你已经拥有了。

构建应用程序

我们已经准备好构建这个应用程序了。确保您仍然处于新目录的顶层。这是什么ls应显示:

$ ls Dockerfile app.py requirements.txt

现在运行Build命令。这将创建一个Docker映像,我们将使用它进行标记-t所以它有个友好的名字。

docker build -t friendlyhello .

你的形象在哪里?它在您机器的本地Docker映像注册表中:

$ docker images REPOSITORY TAG IMAGE ID friendlyhello latest 326387cea398

运行应用程序

运行应用程序,使用以下方法将机器的端口4000映射到容器的已发布端口80-p*

docker run -p 4000:80 friendlyhello

您应该会看到Python正在为您的应用提供服务的通知http://0.0.0.0:80。但是该消息来自容器内部,它不知道你将该容器的端口80映射到4000,从而制作正确的URL http://localhost:4000

转到Web浏览器中的URL,查看网页上的显示内容,包括“HelloWorld”文本、容器ID和Redis错误消息。

您还可以使用curl命令在shell中查看相同的内容。

$ curl http://localhost:4000 <h3>Hello World!</h3><b>Hostname:</b> 8fc990912a14<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>

*该端口重新映射为4000:80是为了证明你EXPOSEDockerfile,还有你publish使用docker run -p在后面的步骤中,我们将只将主机上的端口80映射到容器中的端口80,然后使用http://localhost...

命中CTRL+C在你的终点站辞职。

现在让我们在后台以分离模式运行该应用程序:

docker run -d -p 4000:80 friendlyhello

你得到你的应用程序的长容器ID,然后被踢回你的终端。您的容器正在后台运行。您还可以看到缩写的容器IDdocker container ls%28并且在运行命令%29时两者都可以互换工作:

$ docker container ls CONTAINER ID IMAGE COMMAND CREATED 1fa4ab2cf395 friendlyhello "python app.py" 28 seconds ago

你会看到的CONTAINER ID匹配正在进行的http://localhost:4000...

现在用docker stop若要结束该进程,请使用CONTAINER ID,就像这样:

docker stop 1fa4ab2cf395

分享你的形象

为了演示我们刚刚创建的图像的可移植性,让我们上传构建的映像并在其他地方运行它。毕竟,当您想要将容器部署到生产中时,您将需要学习如何推送到注册表。

注册表是存储库的集合,存储库是图像的集合--有点像GitHub存储库,只是代码已经构建。注册中心上的帐户可以创建许多存储库。大docker默认情况下,CLI使用Docker的公共注册表。

:我们在这里使用Docker的公共册表,仅仅是因为它是免费的和预先配置的,但是有许多公共册表可供选择,您甚至可以使用码头受信任登记处...

用您的码头ID登录

如果您没有码头帐户,请在Cloud.docker.com请记下你的用户名。

登录到本地计算机上的Docker公共注册表。

docker login

标记图像

将本地映像与注册表上的存储库关联的符号是username/repository:tag标记是可选的,但建议使用它,因为它是注册表用于为Docker图像提供一个版本的机制。为上下文提供存储库和标记有意义的名称,如get-started:part1。这将把图像放在get-started存储库并将其标记为part1...

现在,把它放在一起标记图像。跑docker tag image使用您的用户名、存储库和标签名,以便图像将上载到您想要的目的地。该命令的语法是:

docker tag image username/repository:tag

例如:

docker tag friendlyhello john/get-started:part1

跑码头形象才能看到你的新标记图像。%28你也可以使用docker image ls.%29

$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE friendlyhello latest d9e555c53008 3 minutes ago 195MB john/get-started part1 d9e555c53008 3 minutes ago 195MB python 2.7-slim 1c7128a655f6 5 days ago 183MB ...

发布图像

将标记的图像上载到存储库:

docker push username/repository:tag

一旦完成,这个上传的结果是公开的。如果你登录到码头枢纽,您将看到新的图像,在那里,它的拉命令。

从远程存储库中提取并运行映像

从现在开始,你可以用docker run并使用以下命令在任何机器上运行您的应用程序:

docker run -p 4000:80 username/repository:tag

如果映像在机器上本地不可用,Docker将从存储库中提取它。

docker image rm <image id>

$ docker run -p 4000:80 john/get-started:part1 Unable to find image 'john/get-started:part1' locally part1: Pulling from orangesnap/get-started 10a267c67f42: Already exists f68a39a6a5e4: Already exists 9beaffc0cf19: Already exists 3c1fe835fb6b: Already exists 4c9f1fa8fcb8: Already exists ee7d8f576a14: Already exists fbccdcced46e: Already exists Digest: sha256:0601c866aab2adcc6498200efd0f754037e909e5fd42069adeff72d1e2439068 Status: Downloaded newer image for john/get-started:part1 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)

*如果不指定:tag这些命令的一部分,标记为:latest将在构建和运行映像时假设。Docker将使用没有指定%28标记而运行的映像的最后一个版本,而不一定是最近的映像%29。

不管在哪里docker run执行时,它将提取您的图像以及Python和requirements.txt运行你的代码。所有这些都是在一个整洁的小包中一起运行的,主机只需要安装Docker就可以运行它了。

第二部分结论

这一页就这么多了。在下一节中,我们将学习如何通过在服务...

继续第3部分

重述和备忘单%28可选%29

这是本页所涵盖内容的终端记录*

下面列出了这个页面中的基本Docker命令,以及一些相关的命令,如果您想在继续之前进行一番探索的话。

docker build -t friendlyname . # Create image using this directory's Dockerfile docker run -p 4000:80 friendlyname # Run "friendlyname" mapping port 4000 to 80 docker run -d -p 4000:80 friendlyname # Same thing, but in detached mode docker container ls # List all running containers docker container ls -a # List all containers, even those not running docker container stop <hash> # Gracefully stop the specified container docker container kill <hash> # Force shutdown of the specified container docker container rm <hash> # Remove specified container from this machine docker container rm $(docker container ls -a -q) # Remove all containers docker image ls -a # List all images on this machine docker image rm <image id> # Remove specified image from this machine docker image rm $(docker image ls -a -q) # Remove all images from this machine docker login # Log in this CLI session using your Docker credentials docker tag <image> username/repository:tag # Tag <image> for upload to registry docker push username/repository:tag # Upload tagged image to registry docker run username/repository:tag # Run image from a registry

容器python代码编码构建推送运行