构建镜像及容器编排
本篇文章参考了示例。
2018-04-04 更新:
改用基于 alpine 的镜像,在容量上较默认镜像更小。
使用 Dockerfile 创建镜像
编写 WEB 应用
之前,我们直接用官方的 MySQL 镜像创建了一个 MySQL 实例,但若想把自己的应用通过 Docker 部署,那还是需要通过 Dockerfile 构建自己的镜像。
首先,我们利用 python 的 flask 框架建立一个 hello world 的 web 应用。
# app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
if __name__ == '__main__':
# 默认端口为5000
app.run(host='0.0.0.0', debug=True)
在当前目录下,运行python app.py
即可启动应用。
然后,我们在浏览器中输入http://localhost:5000就能看到熟悉的 hello world。
编写 Dockfile
在当前目录下,我们先建立一个Dockerfile文件,然后键入以下内容。
# 基于alpine的python3.6镜像开始构建
FROM python:alpine3.6
# 切换工作目录至/code(可以理解为cd ./code)
WORKDIR /code
# 将代码文件添加到镜像的/code目录下
ADD ./app.py .
# 安装flask库
# 这里使用了清华的镜像源,为了安装的快一些
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple flask
# 运行
CMD [ "python", "app.py" ]
随后,启动一个 PowerShell 窗口,并切换到当前目录下。
# 构建镜像
# -t 表示将该镜像命名为demo,并打上flask的标签
docker build -t demo:flask .
这边需要注意的是最后还有一个.
,代表在当前目录下查找Dockerfile。
在成功构建之后,我们来启动这个镜像的一个实例。
# 启动容器
# --name 参数将该容器命名为demo.flask,方便后续操作
# -d 参加将容器切入后台运行,网上的教程也称为守护进程
# -p 参数将容器内的5000端口,映射到本地的5000端口,使得我们能在本地访问
docker run --name demo.flask -d -p 5000:5000 demo:flask
至此,一个使用 Docker 部署的 WEB 应用就完成了,我们可以通过浏览器访问http://localhost:5000看到和之前一样的 Hello World 界面。
Docker 镜像中有什么?
其实,我也不是特别清楚 Docker 镜像中到底包含了什么。但我们还是看到在基于 python 3.6 的镜像上,我们添加了什么。
通过docker exec -it demo.flask bash
,我们进入容器内部,键入ls
查看当前目录下的文件。
我们可以看到的是,进入后的默认目录就是我们在Dockerfile中设置的/code,同时,里面有我们添加的 app.py 文件。
另外,如果有兴趣,还可以再看一下pip list
里面除了最基础的 pip 和 wheel,其余的就是我们在Dockerfile中使用 pip 安装的库。
使用 docker-compose 编排容器
很多时候,我们的应用往往不能完全塞入同一个容器中,比如需要连接数据库的情况,这时候就需要多个容器之间的协调。Docker 对此也有一个利器,docker-compose。在默认情况下,docker-compose 会随 docker 一同安装好。这里,我根据网上的教程,简单的说下 docker-compose 的使用。
编写一个基于 redis 的 web 应用
redis 是一个内存数据库,可以用来作为应用缓存,这里我们通过 redis 和 flask 实现一个统计访问次数的应用。
首先,修改之前的 WEB 应用,加入 redis 支持。
from flask import Flask
from redis import Redis
app = Flask(__name__)
# 注意,此处的host需和docker-compose中redis的service名相同
redis = Redis(host='redis', port=6379)
@app.route('/')
def hello():
count = redis.incr('hits')
return 'Hello World! 此页面已被访问%d次。\n' % count
if __name__ == "__main__":
app.run(host='0.0.0.0', debug=True)
在Dockerfile中,使用 pip 安装 redis 库。
FROM python:alpine3.6
WORKDIR /code
ADD ./app.py .
# 修改这里,添加redis库
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple flask redis
CMD [ "python", "app.py" ]
自此,一个具有访问次数统计的 WEB 应用就完成了。。。?
显然,还缺少一步。
编写 docker-compose.yml
既然提到了 docker-compose,那总是要用的。在同一目录下,我们建立一个docker-compose.yml
,键入以下内容。
# 由于一些未知的编码原因,若要复制此段配置文件,请手动去掉注释
# 声明使用version 3的docker-compose.yml格式
# 详情可以参考:https://docs.docker.com/compose/compose-file/
version: "3"
# 定义有关服务
services:
# 使用官方的alpine版redis镜像创建redis实例
# 注意这里的redis,指的是服务名,需和之前host中的对应
# 至于原因,之后再解释
redis:
image: "redis:alpine"
# 我们的WEB应用,这里构建为demo:flask-redis镜像
web:
image: "demo:flask-redis"
build: .
# 添加对redis服务的依赖
depends_on:
- redis
# 映射5000端口
ports:
- "5000:5000"
保存后,我们在当前目录下打开 PowerShell 窗口,执行docker-compose build
来完成构建。
然后,使用docker-compose up -d
来启动应用。
访问http://localhost:5000可以看到如下界面。
使用docker ps
,我们也可以看到两个被启动的容器。
至此,应该算是完成了吧。。。
另外,补充一条,如果不再需要这两个容器,可以使用docker-compose down -v
来删除。注意~记得加-v 参数,因为 redis 容器会创建一个数据卷,如果多次使用不删除的话。。emmm。。硬盘大就当我没说。