参考文档:Get Started, Part 2: Containers
Prerequisites
已安装docker
Introduction
层次结构:
- Top level: stack,定义service之间的交互,将会在Part 5介绍
- Middle level: service,定义container在production期间的行为,将会在Part 3介绍
- Bottom level: container(本节介绍)
Your new development environment
过去,如果你需要开发一个Python应用,首先就是要在电脑上安装一个python的运行环境,但是,这需要你的电脑非常适合你的应用,并且需要match你的开发环境。
使用Docker,你可以grab一个轻量级的Python环境作为一个镜像,不必安装。然后,你的开发可以包括基础的Python镜像、你的code,从而保证你的应用、依赖、运行环境打包。
这些可移植的images称为Dockerfile
使用Dockerfile定义一个container
Dockerfile定义了你的container中的环境会运行的内容。对于一些如网络接口、磁盘驱动的资源访问在环境中被虚拟化了,这些与你的系统隔绝开来,所以你需要将这些ports映射到外界,明确哪些文件是你想拷贝到环境中的。然而,这样做之后,你可以期待你在Dockerfile中定义的build版本在任何地方都有相同的运行效果。
创建一个新的目录,进入该目录,创建一个文件叫做Dockerfile
,复制粘贴如下内容保存。注释语句解释了每一行的作用。
1 | # filename: Dockerfile |
Tips: 使用代理服务器
代理服务器可以在你的container运行的时候屏蔽连接你的web app的请求,如果你使用了代理服务器,在Dockerfile
的pip
指令前添加如下行,使用ENV
名来指定你的代理服务器
1 | # Set proxy server, replace host:port with values for your servers |
The app itself
创建另外两个文件requirements.txt
和app.py
,将他们放到和Dockerfile
相同的目录中。当Dockerfile
被创建的称为image的时候,由于Dockerfile中的ADD
指令,app.py
和requirements.txt
会出现,由于EXPOSE
指令,通过http可以访问。
1 | # filename: requirements.txt |
1 | # filename: app.py |
现在我们看到pip install -r requirements.txt
将会为Python安装Flask和Redis库,这个应用会显示环境变量NAME
,同样会输出socket.gethostname()
的返回值。最终,因为Redis没有运行(由于我们只是安装了Python库,而不是Redis本身),我们可以预期到,在这里会fail并且报一些error。
注意:在contaner内部访问host的名称返回container的ID,如同可执行文件的运行ID一样。
就这样,你的系统不需要Python或者requirements.txt
文件中的任何东西,也不需要创建或者运行这个镜像安装到你的系统中。他不需要你真的设置一个Python和Flask环境,但是你已经有了。
Build the app
我们已经创建了这个app,确保你当前目录下有三个文件
1 | [root@digitalocean docker]# ls -l |
现在运行创建指令,这会创建一个Docker镜像,我们将使用-t
标记来给他其一个友好的名字。
1 | [root@digitalocean docker]# docker build -t friendlyhello . |
你创建的image在哪里?在你电脑的本地Docker image的registry中
1 | [root@digitalocean docker]# docker image ls |
Run the app
运行app,通过-p
标记,使你电脑的4000端口映射到container的80端口
1 | [ ] |
这样就可以看到Python运行在http://0.0.0.0:80
上了,但是这个消息是来自container内部,通过http://localhost:4000
可以访问,当然,如果你是挂在云服务器上,那么将地址中的localhost
换成你主机的ip,这样就可以访问了。
注意:如果你使用Docker Toolbox on Windows 7的话,使用电脑的主机IP而不是localhost,比如http://192.168.99.100:4000/。可以通过命令`docker-machine ip`来查看ip地址
你也可以通过curl
命令来获取相同的内容
1 | $ curl http://localhost:4000 |
这个端口映射是用来展示Dockerfile中EXPOSE
的端口和你发布的时候使用docker run -p
的区别。在后续的步骤中,我们将会用主机的80端口和container的80端口进行映射,这样就可以通过http://localhost
访问了
在终端中按CTRL+C
以退出。
在Windows中,显式的停止container
在windows系统中,ctrl+c并不会停止container,所以先按ctrl+c获取返回的提示,然后输入docker container ls
显式运行中的container,然后通过docker container stop <Container NAME or ID>
来停止container,否则你会报错当你下一步充实重新执行这个container的时候
我们现在来执行这个app通过分离模式(-d)
1 | docker run -d -p 4000:80 friendlyhello |
你会得到一个对应你app的很长的contianer ID,然后回到你的终端。你的container此时在后台运行。你可以通过docker container ls
指令看到更简短的conatiner ID。然后可以通过docker container stop 1fa4ab2cf395
来停止你的container,这里请将1fa4ab2cf395
替换为你的container ID。
Share your image
为了展现我们刚才创建的东西有多么强大的可移植性,让我们把它上传,在任何地方运行。不管怎么说,当你想要部署conatiner的时候,你需要知道如何push到registries中。
一个registries是一个仓库(repositories)的集合(collection),一个仓库(repositories)是一系列的images,有点像GitHub的仓库,除了代码已经运行好了。一个帐号中的一个registry可以创建多个仓库。docker CLI默认使用Docker的公共registry。
注意:在这里我们使用Docker的公共registry,仅仅是因为它是免费并且事先配置好的,但是有很多公共的registry可选,你同样可以通过Docker Trusted Registry创建你自己的registry
Log in with your Docker ID
如果你没有Docker帐号,可以通过cloud.docker.com注册,请注意你的用户名。
在你的本机上登录你的Docker公共registry
1 | docker login |
Tag the image
通过usernam/repository:tag
来关联本地image和registry中的仓库。tag是可选的,但是是推荐的,因为这是docker给image版本的方式。给你的repo和tag有意义的名字,比如get-started:part2
。这就会把镜像存在get-started
仓库中,并且给它打上part2
的标记。
现在,我们把这些放在一起,并且对这个image打上tag。运行docker tag image`和username,仓库名,和tag名称,这样image会上传到你想要的重点上,语法如下:
1 | docker tag image username/repository:tag |
比如,
1 | docker tag friendlyhello john/get-started:part2 |
运行docker image ls
就可以看到你新打tag的image了
1 | [root@centos-s-1vcpu-1gb-sfo2-01 1.1 simple web app]# docker image ls |
Publish the image
上传你打标记了的image到仓库
1 | [root@centos-s-1vcpu-1gb-sfo2-01 1.1 simple web app]# docker push manyfun711/get-started:part2 |
在完成之后,这个结果是公开可见的,如果你登录了Docker hub,你可以看到一个新的image。
Pull and run the image from the remote repository
从现在开始,你可以使用docker run
来运行你的app使用这一行指令
1 | docker run -p 4000:80 manyfun711/get-started:part2 |
如果这个image在本地没有,那么Docker就回将它从repo中pull下来。
1 | ~ docker run -p 4000:80 manyfun711/get-started:part2 |
不论docker run
指令在哪里执行,它都会pull下来你的image,同时还有你的python和所有requirements.txt
中的以来,并且可以运行你的code。这些内容会以一个较小的形式一并下来,你也不需要安装任何东西从而让docker运行。
Conclusion of part two
这就是本节所有内容了,在下一个section中,我们将会学到如何扩大我们的应用,让这个container运行在一个service中