🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 构建镜像及容器编排 本篇文章参考了[示例](https://yeasy.gitbooks.io/docker_practice/content/compose/usage.html)。 > 2018-04-04 更新: > > 改用基于alpine的镜像,在容量上较默认镜像更小。 ## 使用Dockerfile创建镜像 ### 编写WEB应用 之前,我们直接用官方的MySQL镜像创建了一个MySQL实例,但若想把自己的应用通过Docker部署,那还是需要通过Dockerfile构建自己的镜像。 首先,我们利用python的flask框架建立一个hello world的web应用。 ```python # 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`即可启动应用。 ![启动Flask](https://box.kancloud.cn/8e55bf5f7f76e91bb0f37dea8c40ee78_960x520.png) 然后,我们在浏览器中输入[http://localhost:5000](http://localhost:5000)就能看到熟悉的hello world。 ![helloworld](https://box.kancloud.cn/000c9f338135b195b14d3fdf2c9eb623_960x520.png) ### 编写Dockfile 在当前目录下,我们先建立一个**Dockerfile**文件,然后键入以下内容。 ```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窗口,并切换到当前目录下。 ```PowerShell # 构建镜像 # -t 表示将该镜像命名为demo,并打上flask的标签 docker build -t demo:flask . ``` 这边需要注意的是最后还有一个`.`,代表在当前目录下查找**Dockerfile**。 在成功构建之后,我们来启动这个镜像的一个实例。 ```PowerShell # 启动容器 # --name 参数将该容器命名为demo.flask,方便后续操作 # -d 参加将容器切入后台运行,网上的教程也称为守护进程 # -p 参数将容器内的5000端口,映射到本地的5000端口,使得我们能在本地访问 docker run --name demo.flask -d -p 5000:5000 demo:flask ``` 至此,一个使用Docker部署的WEB应用就完成了,我们可以通过浏览器访问[http://localhost:5000](http://localhost:5000)看到和之前一样的Hello World界面。 ### Docker镜像中有什么? 其实,我也不是特别清楚Docker镜像中到底包含了什么。但我们还是看到在基于python 3.6的镜像上,我们添加了什么。 通过`docker exec -it demo.flask bash`,我们进入容器内部,键入`ls`查看当前目录下的文件。 ![镜像文件信息](https://box.kancloud.cn/5a34cc1ad4c24867aee514d138f73b8f_572x203.png) 我们可以看到的是,进入后的默认目录就是我们在**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支持。 ```python 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库。 ```Dockerfile 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`,键入以下内容。 ```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](http://localhost:5000)可以看到如下界面。 ![累计访问界面](https://box.kancloud.cn/94481803103f98e985faa0f237d757b5_795x513.png) 使用`docker ps`,我们也可以看到两个被启动的容器。 ![容器编排](https://box.kancloud.cn/6d2dba8d4d569af92c851c1b06ee7e00_1091x502.png) 至此,应该算是完成了吧。。。 另外,补充一条,如果不再需要这两个容器,可以使用`docker-compose down -v`来删除。注意~记得加-v参数,因为redis容器会创建一个数据卷,如果多次使用不删除的话。。emmm。。硬盘大就当我没说。