前言
大家好,我是洋子。在文章《Docker 进阶指南(上)- 使用Dockerfile自定义镜像》介绍了使用DockerFile
文件自定义Docker镜像方法,编写好DockerFile
文件后,执行docker build
命令,即可生成一个镜像,我们再使用docker run
命令,即可运行该镜像所生成的容器
但我们使用DockerFile
自定义的都是单个镜像,然后手动执行docker run
运行单个容器,在实际工作当中,我们需要同时使用到多个容器(如Mysql容器,Nginx容器等),去部署完整的Web服务,那要是想同时部署多个Docker 容器该怎么办呢
这时候需要用到Docker-Compose
容器编排工具即可解决这个问题
Docker-Compose 使用方法
Compose 是用于定义和运行多容器 Docker 应用程序的工具
在Docker官网上,提供了使用Docker-Compose
的详细例子,https://docs.docker.com/compose/gettingstarted/,下面根据这个例子来操作一遍,部署Python Web开发项目
- 安装下载。在已经安装好Docker环境后(Docker的安装方法,可以查看文章Docker快速入门指南),执行以下命令安装
Docker-Compose
# 官方下载源,安装慢
sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker- compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 其他下载源,安装快
sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
安装完毕后,使用docker-compose version
验证安装结果,出现以下信息代表安装成功
[root@yangzi ~]# docker-compose version
docker-compose version 1.25.5, build 8a1c60f6
docker-py version: 4.1.0
CPython version: 3.7.5
OpenSSL version: OpenSSL 1.1.0l 10 Sep 2019
- 创建并进入项目目录
mkdir composetest
cd composetest
- 在项目目录下,创建程序入口
app.py
import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)
@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)
- 创建
requirements.txt
,此文件存放项目当中需要拉取的依赖包
flask
redis
- 创建
Dockerfile
文件,用于定义Python环境的镜像
# syntax=docker/dockerfile:1
# 基础镜像基于Python3.7
FROM python:3.7-alpine
# 设置工作目录为`/code`
WORKDIR /code
# 设置两个环境变量,启动Flask项目时会读取
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
# 安装gcc等其他依赖
RUN apk add --no-cache gcc musl-dev linux-headers
# 拷贝requirements.txt到工作目录,并且安装python依赖
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
# 容器暴露端口5000
EXPOSE 5000
# 把当前项目目录里的内容,拷贝到容器里的工作目录/code
COPY . .
# 容器启动时,执行命令flask run
CMD ["flask", "run"]
- 在项目目录下创建 Compose 文件,名字为
docker-compose.yml
,该文件格式为yaml
version: "3"
services:
web:
build: .
ports:
- "8000:5000"
redis:
image: "redis:alpine"
这里先简单介绍一下 Compose 文件的格式含义
version
表示指明Compose文件版本,可以是2.x或者3.xservices
表示定义了两个服务,用于容器创建,第一个服务名为web
,这里使用build关键字,后面还有一个.
表示当前目录,它的含义和命令docker build
一样,即编译当前目录下的Dockerfile文件创建镜像,同时映射端口8000对应于容器里面的5000端口- 第二个服务名为
redis
,直接使用了官方镜像redis:alpine
- Compose 文件当中更多字段含义,可以查看官方文档
https://docs.docker.com/compose/compose-file/
- 执行命令
docker-compose up -d
就可以同时创建两个容器(docker ps 命令可以查看创建的容器),-d
参数表示后台执行
[root@yangzi composetest]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a84114348ef8 composetest_web "flask run" 24 minutes ago Up 9 minutes 0.0.0.0:8000->5000/tcp, :::8000->5000/tcp composetest_web_1
255dea45b4d6 redis:alpine "docker-entrypoint.s…" 24 minutes ago Up 9 minutes 6379/tcp composetest_redis_1
最后用curl http://127.0.0.1:8000
命令,验证一下服务的运行情况,也可以用hostname -i
查看到本机的ip,用本地ip:8000
端口,在浏览器访问查看效果
[root@zhouyueyang composetest]# curl http://127.0.0.1:8000
Hello World! I have been seen 1 times.
- 如果我们的项目代码,要进行多次修改,按照目前Compose文件的定义,我们需要重新创建容器,可以继续优化一下Compose文件,进行持久化绑定,如我们使用到
volumes
字段,将本地当前的目录绑定到容器里面的/code
目录,在本地目录下修改代码后会实时同步,就不再需要重新创建容器了
version: "3"
services:
web:
build: .
ports:
- "8000:5000"
volumes:
- .:/code
environment:
FLASK_DEBUG: True
redis:
image: "redis:alpine"
Docker 容器数据卷
我们现在已经知道Docker将应用和运行的环境打包形成容器运行,所以容器内产生的数据,都在容器内保存,如果我使用了MySQL容器,不小心把容器删了,所有数据就没有了,这不就直接删库跑路了
那如何将容器内的数据同步到本地,进行持久化存储呢?使用数据卷
技术即可解决这个问题
在docker中,卷的本质是文件或者目录,存在一个或者多个容器中,由docker挂载到容器,不属于联合文件系统;对数据卷的修改会立马生效,对数据卷的更新不会影响镜像
数据卷用于容器的持久化,以及容器间的继承和数据共享
容器卷有哪些特点
-
数据卷可在容器之间共享或重用数据
-
数据卷中的更改不会包含在镜像的更新中
-
卷中的更改可以直接生效
-
数据卷的生命周期一直持续到没有容器使用它为止
如何使用数据卷
- 方法一,通过命令行添加,以运行centos容器为例子
#前提条件,先拉取centos7镜像
docker pull centos:7
# 命令
docker run -it -v 宿主机绝对路径目录:容器内目录 镜像名
# 测试
[root@yangzi ~]# docker run -it -v /home/test:/home centos /bin/bash
查看数据卷是否挂载成功 docker inspect 容器id
,可以看到这里Source就是挂载的宿主机本地的目录
接下来我们在centos
容器/home
目录进行新建文件,在本地宿主机上/home/test
目录就可以出现,同理,在本地卷目录/home/test
下更新文件,centos
容器里面相应目录下,也会进行内容更新
下面的操作就是在宿主机挂载的卷目录下新建了xxx.java
文件,自动同步到容器里面
[root@yangzi test]# touch xxx.java
[root@yangzi test]# ls
xxx.java
[root@yangzi test]# docker attach 531a8f70f60c
[root@531a8f70f60c /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@531a8f70f60c /]# cd /home
[root@531a8f70f60c home]# ls
xxx.java
- 其余使用方法。在
Dockerfile
和Compose
文件当中同样可以使用到数据卷,只是定义的语法上略有不同,在之前文章《Docker 进阶指南(上)- 使用Dockerfile自定义镜像》,以及本篇文章均有相关介绍,这里就不再重复讲解了
docker的常用命令大总结
- 操作容器的常用命令有
docker ps
、docker run
、docker exec
、docker stop
- 操作镜像的常用命令有
docker images
、docker rmi
、docker tag
、docker build
- 操作镜像仓库的常用命令有
docker pull
、docker push
如果前面的内容都已经学完了,看这张图就比较容易了,Docker命令都是基于Registry
镜像仓库和Images
镜像,Container
容器这三个角色展开,其中的大部分命令我们都使用过了
结束语
到这里,Docker的系列的三篇文章就完结了,后面即将开启学习新的容器技术k8s
,毕竟这才是目前容器技术的主角
如果你觉得本篇文章对你有帮助,麻烦点一下【赞】和【在看】,你的支持就是我前进的动力