资讯专栏INFORMATION COLUMN

Part 2: Containers

Soarkey / 814人阅读

摘要:在默认情况下使用的公共注册表。注意我们将在这里使用的公共注册表,因为它是免费和预配置的,但是有许多公共注册中心可供选择,而且您甚至可以使用可信注册表建立您自己的私有注册表。标记镜像将本地映像与注册表中的存储库关联的符号是。

要求

安装了1.13或者更高版本的Docker

阅读了Part1中的定位(我没写)

介绍

是时候用Docker构建一个app了。我们会从构建这样一个app的最底层开始,容器——我们这节所介绍的内容。在这层之上是服务,服务定义了容器们的在生产中的行为,在第3章介绍。最上层的是堆,定义了服务的交互行为,在第5章介绍。

堆(Stack)

服务(Services)

容器(container)

新开发环境

使用docker,您可以直接获取一个可移植的Python运行时作为映像。然后,您的构建可以在应用程序代码旁边包含基本的Python映像,确保应用程序、它的依赖项和运行时环境一起运行。

Dockerfile定义一个容器

Dockerfile将定义容器内环境的内容。访问像网络接口和磁盘驱动器之类的资源在这个环境中是虚拟化的,这与系统的其他部分是隔离的,因此您必须将端口映射到外部世界,并具体地说明您想要“复制”到该环境中的文件。然而,在做了这些之后,您可以期望在这个Dockerfile中定义的应用程序的构建在运行的任何地方都是完全相同的。

Dockerfile

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

</>复制代码

  1. # Use an official Python runtime as a parent image
  2. FROM python:2.7-slim
  3. # Set the working directory to /app
  4. WORKDIR /app
  5. # Copy the current directory contents into the container at /app
  6. ADD . /app
  7. # Install any needed packages specified in requirements.txt
  8. RUN pip install --trusted-host pypi.python.org -r requirements.txt
  9. # Make port 80 available to the world outside this container
  10. EXPOSE 80
  11. # Define environment variable
  12. ENV NAME World
  13. # Run app.py when the container launches
  14. CMD ["python", "app.py"]

</>复制代码

  1. 您是否使用了代理服务器?
  2. 代理服务器一旦启动并运行,就可以阻塞连接到您的web应用程序。如果您在代理服务器后面,请在Dockerfile中添加以下几行,使用ENV命令为您的代理服务器指定主机和端口:

</>复制代码

  1. # Set proxy server, replace host:port with values for your servers
  2. ENV http_proxy host:port
  3. ENV https_proxy host:port

这个Dockerfile和我们还没有创建的两个文件有联系,即app.py和requirements.txt。接下来让我们创建这些。

应用程序本身

创建两个更多的文件,requirements.txt和app.py,并将它们放在与Dockerfile相同的文件夹中。这就完成了我们的应用程序,正如您所看到的非常简单。当上述Dockerfile被构建成一个Image,由于Dockerfile的ADD命令会添加requirements.txt和app.py,感谢EXPOSE使app.py的输出可以通过HTTP访问。

requirements.txt

</>复制代码

  1. Flask
  2. Redis
app.py

</>复制代码

  1. from flask import Flask
  2. from redis import Redis, RedisError
  3. import os
  4. import socket
  5. # Connect to Redis
  6. redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
  7. app = Flask(__name__)
  8. @app.route("/")
  9. def hello():
  10. try:
  11. visits = redis.incr("counter")
  12. except RedisError:
  13. visits = "cannot connect to Redis, counter disabled"
  14. html = "

    Hello {name}!

    "
  15. "Hostname: {hostname}
    "
  16. "Visits: {visits}"
  17. return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)
  18. if __name__ == "__main__":
  19. app.run(host="0.0.0.0", port=80)

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

</>复制代码

  1. 注意:当容器内检索容器ID时访问主机名,这就像运行可执行文件的进程ID
    就是这样!您不需要Pythonrequirements.txt中的任何东西在你的系统上,也不会在你的系统上安装或运行这个映像。看起来你并没有真正建立一个包含PythonFlask的环境,但是你有。

构建应用

我们已经准备好构建应用程序,确保您仍然处于新目录的顶层。下面是ls应该展示的:

</>复制代码

  1. $ ls
  2. Dockerfile app.py requirements.txt

现在运行build命令。这创建了一个Docker映像,我们将使用- t标记它,因此它有一个友好的名称。

</>复制代码

  1. docker build -t friendlyhello .

你的构建的Image在哪里?就在你的机器的本地Docker图像注册表中:

</>复制代码

  1. $ docker images
  2. REPOSITORY TAG IMAGE ID
  3. friendlyhello latest 326387cea398

</>复制代码

  1. 提示:您可以使用命令docker images或较新的docker image ls查看所有的镜像。它们给出相同的输出。

运行应用

运行应用程序,使用-p,将您的机器的端口4000映射到容器已经发布的端口80:

</>复制代码

  1. docker run -p 4000:80 friendlyhello

您应该看到一条消息,Python正在以http://0.0.0.0:80为您的应用服务。但是这个消息来自容器内部,它不知道您将该容器的80端口映射到4000,从而使正确的URL http://localhost:4000。
在web浏览器中访问该URL,可以看到web页面上显示的显示内容,包括“Hello World”文本、容器ID和Redis错误消息。

</>复制代码

  1. 注意:如果您在Windows 7上使用Docker工具,使用Docker机器IP而不是localhost。例如,http://192.168.99.100:4000。要查看IP地址,请使用命令docker -machine IP。

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

</>复制代码

  1. $ curl http://localhost:4000
  2. Hello World!

    Hostname: 8fc990912a14
    Visits: cannot connect to Redis, counter disabled

这个端口映射4000:80是为了演示在Dockerfile中公开的内容和使用docker run - p发布的内容之间的区别。在后面的步骤中,我们将把端口80映射到容器中的80端口,并使用http://localhost。
在你的终端按CTRL + C退出。

现在让我们在后台运行应用程序,在分离的模式下:

</>复制代码

  1. docker run -d -p 4000:80 friendlyhello

你得到了你的应用程序的容器长ID,然后被离开你的终端。您的容器将在后台运行。您还可以看到缩写容器ID通过docker container ls(在运行命令时,这两个工作都可以互换):

</>复制代码

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

您将看到匹配http://localhost:4000上的CONTAINER ID

现在使用docker容器停止进程,使用容器ID,例如:

</>复制代码

  1. docker container stop 1fa4ab2cf395
分享你的镜像

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

注册表是存储库的集合,而存储库是镜像的集合——有点像GitHub库,只是代码已经构建好了。注册表上的帐户可以创建许多存储库。docker CLI在默认情况下使用docker的公共注册表。

</>复制代码

  1. 注意:我们将在这里使用Docker的公共注册表,因为它是免费和预配置的,但是有许多公共注册中心可供选择,而且您甚至可以使用Docker可信注册表建立您自己的私有注册表。

使用您的Docker ID登录

如果你没有Docker帐户,在cloud.docker.com注册一个。记下你的用户名。

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

</>复制代码

  1. $ docker login
标记镜像

将本地映像与注册表中的存储库关联的符号是username/repository:tag。标签是可选的,但推荐,因为它是注册中心用来给Docker映像提供一个版本的机制。提供存储库并为上下文标记有意义的名称,例如get - started:part2。这将把镜像放到get-started存储库中,并将其标记为part2。

</>复制代码

  1. docker tag image username/repository:tag

例如:

</>复制代码

  1. docker tag image username/repository:tag

运行docker image以查看新标记的图像。(您也可以使用docker image ls)

</>复制代码

  1. $ docker images
  2. REPOSITORY TAG IMAGE ID CREATED SIZE
  3. friendlyhello latest d9e555c53008 3 minutes ago 195MB
  4. john/get-started part2 d9e555c53008 3 minutes ago 195MB
  5. python 2.7-slim 1c7128a655f6 5 days ago 183MB
  6. ...
发布镜像

将您的标记镜像上载到存储库

</>复制代码

  1. docker push username/repository:tag

一旦完成,这个上传的结果是公开的。如果您登录到Docker Hub,您将在那里看到新的图像,使用它的pull命令。

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

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

</>复制代码

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

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

</>复制代码

  1. $ docker run -p 4000:80 john/get-started:part2
  2. Unable to find image "john/get-started:part2" locally
  3. part2: Pulling from john/get-started
  4. 10a267c67f42: Already exists
  5. f68a39a6a5e4: Already exists
  6. 9beaffc0cf19: Already exists
  7. 3c1fe835fb6b: Already exists
  8. 4c9f1fa8fcb8: Already exists
  9. ee7d8f576a14: Already exists
  10. fbccdcced46e: Already exists
  11. Digest: sha256:0601c866aab2adcc6498200efd0f754037e909e5fd42069adeff72d1e2439068
  12. Status: Downloaded newer image for john/get-started:part2
  13. * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)

</>复制代码

  1. 注意:如果您没有指定这些命令的标记部分:tag,那么将会假定您在构建和运行映像时都将使用最新的标记:latestDocker将使用没有指定标记的图像的最后一个版本(不一定是最近的图像)。

无论docker运行在哪里,它都会拉出您的映像,以及Python以及来自需求的所有依赖项requirements.txt,并运行您的代码。它在一个整洁的小程序包中一起运行,而主机不需要安装任何东西,而是安装Docker来运行它。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/27113.html

相关文章

  • Docker 系列教程,Part 8: Docker Remote API

    摘要:注这篇文章是系列教程中的一篇,本篇文章由发布,原文地址在前面的文章中,作为正在进行的教程系列的一部分,我们讨论了。这个系列的其他教程 注:这篇文章是系列教程中的一篇,本篇文章由 Flux7 Labs 发布,原文地址 Docker Tutorial Series, Part 8: Docker Remote API 在前面的文章中,作为正在进行的 Docker 教程系列的一部分...

    姘搁『 评论0 收藏0
  • Laravel Container (容器) 概念详解 (上)

    摘要:上文书,创建对象需要先创建对象。创建对象的杂活是嵌入在中的。对象使用来管理依赖关系非常好,但不是必须的。很容易实现,但手工维护各种乱七八糟的对象还是很麻烦。所有文章均已收录至项目。 本文翻译自 Symfony 作者 Fabien Potencier 的 《Dependency Injection in general and the implementation of a Depend...

    FullStackDeveloper 评论0 收藏0
  • 从头开始,彻底理解服务端渲染原理(8千字汇总长文)

    摘要:到此,就初步实现了一个组件是服务端渲染。服务端渲染完成页面结构,浏览器端渲染完成事件绑定。但是,在服务端渲染中却出现了问题。根据这个思路,服务端渲染中异步数据的获取功能就完成啦。 大家好,我是神三元,这一次,让我们来以React为例,把服务端渲染(Server Side Render,简称SSR)学个明明白白。 这里附上这个项目的github地址:https://github.com/...

    hiyang 评论0 收藏0
  • Flux7 Docker 系列教程(八):Docker Remote API

    摘要:本系列教程翻译自,系列共有九篇,本文译自第八篇。是将会用来取代命令的工具。准备示例系统是,配置文件在。修改完毕后,重启。列出所有容器创建新容器检查容器用于获取容器底层信息。进程列表获取容器内运行进程的列表。下篇文章介绍的是用于镜像操作的。 本系列教程翻译自 Flux7 Docker Tutorial Series,系列共有九篇,本文译自第八篇 Part 8: Docker Rem...

    geekidentity 评论0 收藏0
  • Flux7 Docker 系列教程(八):Docker Remote API

    摘要:本系列教程翻译自,系列共有九篇,本文译自第八篇。是将会用来取代命令的工具。准备示例系统是,配置文件在。修改完毕后,重启。列出所有容器创建新容器检查容器用于获取容器底层信息。进程列表获取容器内运行进程的列表。下篇文章介绍的是用于镜像操作的。 本系列教程翻译自 Flux7 Docker Tutorial Series,系列共有九篇,本文译自第八篇 Part 8: Docker Rem...

    philadelphia 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<