Docker入门六部曲——容器
准备已经安装好Docker 1.13或者以上的版本。读完的上一篇文章(基本引导)。简单的测试一下你的本地环境是否已经OK了:docker run hello-world。介绍让我们开始构建一个Docker应用吧。这篇文章介绍的是,Docker整个结构层次中最底层的一个,那就是容器。上一个层级是服务,服务定义了容器的行为,这会在下一篇文章中介绍。最后一个,也是最高的一个层级,是堆栈,定义了所有
原文链接:http://www.dubby.cn/detail.html?id=8734
准备
- 已经安装好Docker 1.13或者以上的版本。
- 读完的上一篇文章(基本引导)。
- 简单的测试一下你的本地环境是否已经OK了:
docker run hello-world
。
介绍
让我们开始构建一个Docker应用吧。这篇文章介绍的是,Docker整个结构层次中最底层的一个,那就是容器。上一个层级是服务,服务定义了容器的行为,这会在下一篇文章中介绍。最后一个,也是最高的一个层级,是堆栈,定义了所有服务的交互,这在之后也会被介绍。
- Stack(堆栈)
- Services(服务)
- Container(容器)——你正在看的
走进新的开发环境
在没有Docker的时候,如果你想写一个Python应用,你首先要做的是安装一个Python的运行环境。但是,你的机器的环境必须是这样,才能使得应用可以正常执行,而且,服务器也必须有这样的环境。
有了Docker,你可以直接通过镜像来获得一个Python的运行环境,不需要安装哦。然后把你的代码和这个镜像放到一起,当然还要加上你的代码所需的依赖。
这些融合在一起,就形成了一个新的镜像,定义这个融合逻辑的就是Dockerfile
。
使用Dockerfile
来定义一个容器
Dockerfile
是用来定义你的容器。对于一些资源访问,比如网卡、磁盘,在容器里都是虚拟化的,和宿主机都是隔离的,因此,你必须把容器内的资源和宿主机的资源做一个映射;还需要指定你想要把哪些文件copy到你的容器里(比如你的代码)。当然,你还希望这个写好的Dockerfile
在任何地方运行都是一样的。
Dockerfile
创建一个空目录,然后在里面新建一个文件Dockerfile
:
# 使用Python官方镜像作为镜像的基础
FROM python:2.7-slim
# 设置工作空间为/app
WORKDIR /app
# 把当前目录下的文件拷贝到 容器里的/app里
ADD . /app
# 安装requirements.txt中指定的依赖
RUN pip install -r requirements.txt
# 开放80端口
EXPOSE 80
# 设置 NAME 这个环境变量
ENV NAME World
# 当容器启动时,运行app.py
CMD ["python", "app.py"]
这个Dockerfile
中需要的几个文件还没有准备好,app.py
和requirements.txt
,所以我们继续吧。
应用
在Dockerfile
同一个目录下,创建这两个文件。因为ADD
命令需要把这些拷贝进容器里。而且app.py
中的服务器输入端口也正好是80,这会因为配置了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 = "<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
安装了Flask和Redis的库,应用打印出NAME
这个环境变量和socket.gethostname
。最后,因为Redis没有运行(pip安装的只是使用Redis的库,并不是Redis本身),所以我们应该做尝试连接Redis,如果连接失败就打印错误信息。
注意:在容器内部访问主机名时,会检索容器的ID,类似于进程ID。
构建应用
就这样!你不需要安装Python,不需要安装requirements.txt
中指定的任何依赖。看起来,你什么都没做,但是其实你已经做完了。
执行ls
(默认为类Unix环境):
$ ls
➜ demo ls
Dockerfile app.py requirements.txt
现在来执行构建命令。这个会创建一个Docker镜像,-t
可以让你给镜像自定义一个名字:
docker build -t friendlyhello .
你肯定要问要,你的镜像在哪里?他就在你的本地Docker镜像注册中心:
$ docker images
REPOSITORY TAG IMAGE ID
friendlyhello latest 326387cea398
运行你的应用
运行,当然还要映射端口号,我们需要使用-p
:
docker run -p 4000:80 friendlyhello
你可以看到Python启动是提醒你访问http://0.0.0.0:80
。但是不要忘记这个响应是从容器内返回的哦,而我们把容器内的80端口映射到宿主机的4000端口了,所以,我们应该访问http://localhost:4000
。
打开浏览器,可以看到:
你也可以使用curl
来看响应内容:
$ curl http://localhost:4000
<h3>Hello World!</h3><b>Hostname:</b> 8fc990912a14<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
按键CTRL+C
可以退出Docker。
现在试试在后台运行这个Docker应用:
docker run -d -p 4000:80 friendlyhello
执行完后台运行的命令后,你可以获得一个容器的ID
➜ demo docker run -d -p 4000:80 friendlyhello
b0054baaca448f3b30b01004de98be45fbb9aaccd850137629220bbc730b0a1a
你也可以使用docker ps
来看到缩短的容器ID:
➜ demo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b0054baaca44 friendlyhello "python app.py" About an hour ago Up About an hour 0.0.0.0:4000->80/tcp keen_beaver
当然也可以在http://localhost:4000
上看到这个容器ID。你可以使用docker stop
来结束这个进程,后面要加上容器ID哦:
➜ demo docker stop b0054baaca44
b0054baaca44
分享你的镜像
为了展示Docker的便捷性,我们来尝试上传这个镜像吧,然后再证明可以run anywhere
。
注册中心就是一个镜像的仓库的集合——有点类似GitHub(代码仓库)。一个账号可以创建很多个仓库。docker
默认情况下就是Docker公共注册中心。
我们这里使用Docker的公共注册中心,仅仅是因为他是免费而且是默认的。不过还是有很多公开的注册中心可以选择的,甚至你可以设置一个私服。
登录
如果你没有账号,那你需要先注册一个。
然后在你的本机上使用:
docker login
给镜像打标签
镜像的标记一般这样命名username/repository:tag
。tag是可选的,不过推荐使用tag,这样可以给镜像加一个版本。建议把仓库名和标签名都起得有意义一些,比如get-started:part1
。这样会把镜像放到get-started
仓库里,打上part1
的标签。
语法是docker tag image username/repository:tag
,现在开始用命令来尝试打标签吧:
➜ demo docker tag friendlyhello dubbyyoung/get-started:part1
➜ demo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
dubbyyoung/get-started part1 4ac5012183e0 4 hours ago 194 MB
friendlyhello latest 4ac5012183e0 4 hours ago 194 MB
python 2.7-slim d962f7a9f2f1 2 days ago 182 MB
hello-world latest 1815c82652c0 9 days ago 1.84 kB
➜ demo
推送到远端
推送的命令是:
docker push username/repository:tag
我执行的结果是:
➜ demo docker push dubbyyoung/get-started:part1
The push refers to a repository [docker.io/dubbyyoung/get-started]
b57286e58751: Pushed
7b71bca6a91c: Pushed
cdc93fd01629: Pushed
553c628e7577: Mounted from library/python
8f02c55c4e74: Mounted from library/python
15d2fe96bb43: Mounted from library/python
0d960f1d4fba: Mounted from library/python
part1: digest: sha256:6d816f3a86c74e8855cef96750ff1da98eb11747c4a31cbb486b92dd20e075e6 size: 1787
随时随地都可以执行了
到了这一步,你可以使用docker run
在任何一个机器上运行了:
docker run -p 4000:80 username/repository:tag
如果本地没有这个镜像,Docker会自动去远端拉取:
➜ demo docker run -p 4000:80 dubbyyoung/get-started:part1
* Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
注意:如果你不指定标签
:tag
,那么缺省的就是:latest
,不管是构建的时候还是运行的时候。
更多推荐
所有评论(0)