©
本文档使用 PHP中文网手册 发布
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.py
和requirements.txt
让我们创造下一个。
再创建两个文件,requirements.txt
和app.py
,并将它们放在同一个文件夹中,Dockerfile
这就完成了我们的应用程序,正如您所看到的,这个应用程序非常简单。当以上Dockerfile
被塑造成一幅图像,app.py
和requirements.txt
会因为这个而出现Dockerfile
氏ADD
命令的输出。app.py
可以通过HTTP访问,这要感谢EXPOSE
命令。
requirements.txt
Flask Redis
app.py
from flask import Flaskfrom redis import Redis, RedisErrorimport osimport 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
是为了证明你EXPOSE
在Dockerfile
,还有你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的公共注册表,仅仅是因为它是免费的和预先配置的,但是有许多公共注册表可供选择,您甚至可以使用码头受信任登记处...
如果您没有码头帐户,请在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部分
这是本页所涵盖内容的终端记录*
下面列出了这个页面中的基本Docker命令,以及一些相关的命令,如果您想在继续之前进行一番探索的话。
docker build -t friendlyname . # Create image using this directory's Dockerfile docker run -p 4000:80 friendlyname # Run "friendlyname" mapping port 4000 to 80docker 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