- 介绍
现在是开始构建Docker应用程序。我们将从这个应用程序的层次结构的底部开始,这个应用程序是一个容器。在这个层次上面是一个服务,它定义了容器在生产中的行为方式,将在第3部分中进行讨论。最后,在顶层是堆栈,定义了所有服务的交互,将在第5部分进行讨论。 - docker开发环境
在过去,如果你要开始编写一个Python应用程序,你的第一步就是在你的服务器上安装一个Python运行库。但是,这会造成你的服务器上的环境必须如此,以使你的应用程序能够按预期运行。
使用Docker,docker具有可移植性,你可以将一个可移植的Python运行时作为一个镜像来获取,无需安装。然后,将基础Python镜像与应用程序代码一起包括在内,包括应用程序所依赖项。
这些可移植的镜像是由一个叫做Dockerfile的东西来定义的。 - 用Dockerfile定义一个容器
Dockerfile将定义你的容器内的环境中发生了什么。这个环境与系统的其他部分是隔离的,所以你必须将端口映射到外部世界,并具体说明你想“拷入”哪些文件那个环境。这样做后,你定义的Dockerfile在生成镜像后,就具有了移植性。
Dockerfile
创建一个名为Dockerfile的文件,将以下内容复制并粘贴到该文件中并保存。Dockerfile中每条语句的注释如下: ##使用官方的Python运行时作为源镜像 FROM python:2.7-slim ##将工作目录设置为/ app WORKDIR /app ##将当前目录内容复制到/ app的容器中 ADD . /app ##安装requirements.txt中指定的任何所需的软件包 RUN pip install --trusted-host pypi.python.org -r requirements.txt ##此容器对外提供端口80 EXPOSE 80 ##定义环境变量 ENV NAME World ##容器启动时运行app.py CMD ["python", "app.py"]
说明:你在代理服务器后面吗?
代理服务器启动并运行后,可以阻止与您的网络应用程序的连接。如果您位于代理服务器的后面,请使用ENV命令为你的代理服务器指定主机和端口,将以下行添加到Dockerfile中:##设置代理服务器,将host:port替换为服务器的值 ENV http_proxy host:port ENV https_proxy host:port
注意:在使用pip之前添加这些行,以便安装成功。
这个Dockerfile引用了一些我们还没有创建的文件,分别是app.py和requirements.txt。接下来创建这些。 - 应用程序本身
创建另外两个文件:requirements.txt和app.py,并将它们放在与Dockerfile同一级目录下。当上面的Dockerfile被内置到镜像中时,由于Dockerfile的ADD命令,app.py和requirements.txt将会出现,并且app.py的输出将可以通过HTTP访问,这要归功于EXPOSE命令。#cat requirements.txt Flask Redis #cat 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没有运行(因为我们只安装了Python库,而不是Redis本身),所以我们在这里尝试使用它将会失败并产生错误信息。
注意:在容器中访问主机的名称将检索容器ID,这与正在运行的可执行文件的进程ID类似。 - 构建应用程序
我们准备构建应用程序。确保你仍然在你的新目录的顶层。ls应该显示:$ ls Dockerfile app.py requirements.txt
现在运行build命令。这会创建一个Docker镜像,我们将使用-t标记,因此它有一个名字。
#docker build -t friendlyhello . 查看创建的镜像,它在你的机器的本地Docker镜像注册表中: $ docker images REPOSITORY TAG IMAGE ID friendlyhello latest 326387cea398
- 运行应用程序
运行应用程序,使用-p(小写)将您的机器的端口4000映射到容器的已发布端口80:#docker run -p 4000:80 friendlyhello
你应该看到一条消息,Python在http://0.0.0.0:80上提供你的应用程序。但是,这个消息来自容器内部,它不知道你将该容器的端口80映射到4000,本地可以使用URL为http:// localhost:4000来访问。
注意:如果您在Windows 7上使用Docker Toolbox,请使用Docker Machine IP而不是本地主机。
例如,http://192.168.99.100:4000/。要查找IP地址,请使用命令docker-machine ip。
您也可以在shell中使用curl命令来查看相同的内容。$ curl http://localhost:4000 <h3>Hello World!</h3><b>Hostname:</b> 8fc990912a1
这个4000:80的端口重映射是为了演示Dockerfile中的EXPOSE与使用docker run -p发布的内容之间的区别。在后面的步骤中,我们将主机上的端口80映射到容器中的端口80,并使用http:// localhost。
现在让我们以分离模式在后台运行应用程序:#docker run -d -p 4000:80 friendlyhello 你得到你的应用程序的容器ID,然后被返回你的终端。你的容器正在后台运行。你还可以使用docker container ls查看容器标识(或者使用docker ps): $ docker container ls CONTAINER ID IMAGE COMMAND CREATED 1fa4ab2cf395 friendlyhello "python app.py" 28 seconds ago 现在使用docker container stop来结束进程,使用CONTAINER ID,如下所示: #docker container stop 1fa4ab2cf395
- 分享镜像
为了演示我们刚刚创建的镜像可移植性,我们上传我们构建的镜像,并在其他地方运行它。毕竟,当你想将容器部署到生产环境中时,你需要学习如何使用注册表(registry)。
一个注册表是一个存储库的集合,一个存储库是一个镜像集合,这有点像GitHub存储库,除了代码已经建立。注册表上的帐户可以创建许多存储库。 Docker CLI默认使用Docker的公共注册表。
注意:我们将在这里使用Docker的公共注册表,因为它是免费的,并且是预配置的,但是有许多公共选项可供选择,甚至可以使用Docker Trusted Registry设置您自己的私有注册表。 - 使用Docker ID登录
如果您没有Docker帐户,请在cloud.docker.com注册一个。记下你的用户名。登录到本地机器上的Docker公共注册表。 $ docker login
- 标记镜像
将本地镜像与注册表中的存储库相关联的符号是username/repository:tag。该标签是可选的,但推荐使用,因为这是注册管理机构为Docker镜像提供版本的机制。给存储库并标记上下文的有意义的名字,比如get-started:part2。这会将图像放入启动存储库,并将其标记为part2。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
- 发布镜像
将标记的镜像上传到存储库: #docker push username/john/get-started:part2 举例如下: #docker push wtf(用户名)/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
无论Docker运行在哪里,它都会将您的镜像,Python以及所有依赖项从requirements.txt中提取出来,并运行您的代码。它们一起旅行在一个整洁的小包里,主机不需要安装任何东西,除了Docker。
原文地址:http://blog.51cto.com/wutengfei/2063990