给你的环境一个快速的测试运行,以确保你所有的设置:
docker run hello-world
介绍
现在是开始构建Docker方式的应用程序的时候了。我们将从这个应用程序的层次结构的底部开始,这个应用程序是一个容器,我们在这个页面上覆盖。在这个层次上面是一个服务,它定义了容器在生产中的行为方式。最后,在顶层是堆栈,定义所有服务的交互。
● 堆
● 服务
● 容器(你在这里)
你的新开发环境
在过去,如果你要开始编写一个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 --trusted-host pypi.python.org -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中,使用以下ENV命令指定代理服务器的主机和端口:
# Set proxy server, replace host:port with values for your servers
ENV http_proxy host:port
ENV https_proxy host:port
在调用之前添加这些行,pip以便安装成功。
这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 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 = “cannot connect to Redis, counter disabled”
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没有运行(因为我们只安装了Python库,而不是Redis本身),所以我们应该期望在这里使用它的尝试将失败并产生错误消息。
注意:在容器中访问主机的名称将检索容器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。
在网络浏览器中转到该URL,查看网页上提供的显示内容。
注意:如果您在Windows 7上使用Docker Toolbox,请使用Docker Machine IP而不是localhost。例如,http://192.168.99.100:4000/。要找到IP地址,请使用该命令docker-machine ip。
您也可以curl在shell中使用该命令来查看相同的内容。
$ curl http://localhost:4000
Hello World!
Hostname: 8fc990912a14Visits: cannot connect to Redis, counter disabled
这个端口重新映射4000:80是为了展示你EXPOSE内部Dockerfile和你publish使用 什么之间的区别docker run -p。在后面的步骤中,我们将主机上的端口80映射到容器中的端口80并使用http://localhost。
打CTRL+C在你的终端退出。
在Windows上,显式停止容器
在Windows系统上,CTRL+C不停止容器。所以,先输入CTRL+C提示符(或打开另一个shell),然后键入 docker container ls列出正在运行的容器,然后 docker container stop 停止容器。否则,当您尝试在下一步中重新运行容器时,将从守护程序中收到错误响应。
现在让我们以分离模式在后台运行应用程序:
docker run -d -p 4000:80 friendlyhello
你得到你的应用程序的长容器ID,然后被踢回你的终端。您的容器正在后台运行。您还可以看到缩写容器ID docker container ls(在运行命令时可以互换使用):
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED
1fa4ab2cf395 friendlyhello “python app.py” 28 seconds ago
你会看到CONTAINER ID匹配的内容http://localhost:4000。
现在docker container stop用来结束这个过程,使用CONTAINER ID如下所示:
docker container stop 1fa4ab2cf395
分享您的镜像
为了演示我们刚刚创建的可移植性,我们上传我们构建的映像,并在其他地方运行它。毕竟,当你想将容器部署到生产环境中时,你需要学习如何推动注册表。
一个注册表是一个存储库的集合,一个存储库是一个图像集合 - 有点像GitHub存储库,除了代码已经建立。注册表上的帐户可以创建许多存储库。该dockerCLI使用泊坞窗的公共注册表默认情况下。
注意:我们将在这里使用Docker的公共注册表,因为它是免费的,并且是预配置的,但是有许多公共选择,甚至可以使用Docker Trusted Registry设置您自己的私有注册表。
使用您的Docker ID登录
如果您没有Docker帐户,请在cloud.docker.com注册一个 。记下你的用户名。
登录到本地计算机上的Docker公共注册表。
$ docker login
标记镜像
将本地映像与注册表上的存储库相关联的符号是 username/repository:tag。该标签是可选的,但推荐使用,因为这是注册管理机构为Docker镜像提供版本的机制。给存储库并为上下文标记有意义的名称,例如 get-started:part2。这将把图像放入get-started存储库并标记为part2。
现在,把它们放在一起来标记图像。运行docker tag image您的用户名,存储库和标签名称,以便图像将上传到您想要的目的地。该命令的语法是:
docker tag image username/repository:tag
例如:
docker tag friendlyhello john/get-started:part2
运行docker镜像以查看新标记的镜像。(你也可以用docker image ls。)
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
friendlyhello latest d9e555c53008 3 minutes ago 195MB
john/get-started part2 d9e555c53008 3 minutes ago 195MB
python 2.7-slim 1c7128a655f6 5 days ago 183MB
…
发布镜像
将您的标记图片上传到存储库:
docker push username/repository:tag
一旦完成,这个上传的结果是公开的。如果你登录到Docker Hub,你将会看到那个新的镜像和它的pull命令。
从远程存储库中提取并运行映像
从现在起,您可以使用docker run此命令在任何机器上使用并运行您的应用程序:
docker run -p 4000:80 username/repository:tag
如果图像在机器上本地不可用,Docker将从存储库中取出。
$ docker run -p 4000:80 john/get-started:part2
Unable to find image ‘john/get-started:part2’ locally
part2: Pulling from john/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:part2
* Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
无论在哪里docker run执行,它都会将您的镜像,Python以及所有依赖关系从中拉出requirements.txt,然后运行您的代码。它们一起旅行在一个整洁的小包里,主机不需要安装任何东西,除了Docker来运行它。