5. Docker Compose
Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。通过一个 YAML 文件来配置应用服务,然后使用一个命令即可创建并启动所有服务。
- 基本命令
docker-compose up
# 创建并启动所有服务
docker-compose down
# 停止并移除容器、网络等
docker-compose ps
# 查看运行状态
docker-compose logs
# 查看服务日志 - 示例配置文件
version: '3'
services:
web:
build: . # 使用当前目录的Dockerfile构建镜像
ports:
- "5000:5000" # 映射端口
volumes:
- .:/code # 挂载当前目录到容器内/code目录
depends_on:
- redis # 依赖redis服务
redis:
image: redis:alpine # 使用官方redis镜像
volumes:
- redis-data:/data # 挂载数据卷
volumes:
redis-data: # 定义数据卷
6. Dockerfile
6.1 Dockerfile
Dockerfile 是一个文本文件,用于定义 Docker 镜像的构建过程。通过编写 Dockerfile,可以自动化创建自定义镜像,确保镜像内容的一致性和可重复性。
- Dockerfile 的基本结构:
--------------创建镜像运行----------------------
# 基础镜像
FROM ubuntu:20.04
# 维护者信息
LABEL maintainer="your@email.com"
# 安装依赖
RUN apt-get update && apt-get install -y \
python3 \
python3-pip
# 复制应用代码
COPY . /app
WORKDIR /app
# 安装应用依赖
RUN pip3 install -r requirements.txt
# 暴露端口
EXPOSE 8080
-------------执行容器运行-----------------------
# 定义启动命令
CMD ["python3", "app.py"]
6.2 指令
Dockerfile是一堆指令,在docker build的时候,按照该指令进行操作,最终生成我们期望的镜像
- FROM 指定基础镜像,必须为第一个命令
格式:
FROM <image>:<tag>
示例:
FROM mysql:5.7
注意:
tag是可选的,如果不使用tag时,会使用latest版本的基础镜像 - MAINTAINER 镜像维护者的信息
格式:
MAINTAINER <name>
示例:
MAINTAINER wupeiqi
MAINTAINER wupeiqi@live.com
MAINTAINER wupeiqi <wupeiqi@live.com>
- ENV 设置环境变量
格式:
ENV <key> <value>
ENV <key>=<value>
示例:
ENV myName John
ENV myCat=fluffy
- COPY|ADD 添加本地文件到镜像中 app.py /data/www/info/app.py
格式:
COPY <src>... <dest>
示例:
ADD hom* /mydir/
# 添加所有以"hom"开头的文件
ADD test relativeDir/
# 添加 “test” 到 $WORKDIR/relativeDir/
ADD test /absoluteDir/
# 添加 “test” 到 /absoluteDir/
注意:针对压缩包使用ADD的话,会自动解压。
- WORKDIR 工作目录
格式:
WORKDIR /path/to/workdir
示例:
WORKDIR /a
(这时工作目录为/a)
注意:
通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行 - RUN 构建镜像过程中执行命令
格式:
RUN <command>
示例:
RUN yum install nginx
RUN pip install django
RUN mkdir test && rm -rf /var/lib/unusedfiles
注意:
RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache
参数,如:docker build --no-cache
- CMD 构建容器后调用,也就是在容器启动时才进行调用
格式:
CMD ["executable","param1","param2"]
(执行可执行文件,优先)
CMD ["param1","param2"]
(设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
CMD command param1 param2
(执行shell内部命令)
示例:
CMD ["/usr/bin/wc","--help"]
CMD ping www.baidu.com
注意:
CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。 - ENTRYPOINT 设置容器初始化命令,使其可执行化
格式:
ENTRYPOINT ["executable", "param1", "param2"]
(可执行文件, 优先)
ENTRYPOINT command param1 param2
(shell内部命令)
示例:
ENTRYPOINT ["/usr/bin/wc","--help"]
注意:
ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,
而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。
Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令
CMD 与 ENTRYPOINT 区别
- 使用以下dockerfile构建镜像后执行docker run 镜像id -l会发生报错,因为 docker run 执行的 -l 会覆盖 CMD ,而 -l 不是命令所以报错
- 使用以下dockerfile构建镜像后执行docker run 镜像id -l会正常运行,因为 docker run 执行的 -l 会作为参数传给 ENTRYPOINT
- EXPOSE 暴漏端口
格式:
EXPOSE <port> [<port>...]
示例:
EXPOSE 80 443
EXPOSE 8080
EXPOSE 11211/tcp 11211/udp
注意:
就是一个端口的标识,实际开发时,没什么意义。因为端口的映射会在run命令时进行指定。
6.3 构建镜像与运行容器
- 编写 Dockerfile:创建一个名为 Dockerfile 的文件,定义镜像构建步骤。
- 构建镜像:使用 docker build 命令构建镜像:
docker build -t myapp:1.0 -f Dockerfile --no-cache
.
其中,-t
指定镜像标签,.
表示使用当前目录的 Dockerfile。–no-cache表示无缓存 docker image ls
或者docker images
查看所创建的镜像- 运行容器:使用 docker run 命令基于镜像创建并运行容器:
docker run -d -p 8080:8080 myapp:1.0
其中,-d
表示后台运行,-p 8080:8080
表示将容器的 8080 端口映射到主机的 8080 端口。
实操:
- 创建一个 Dockerfile1 , 并修改文件内容,定义一个简单镜像构建步骤:
- docker build 构建镜像
docker build -f /data1/lsr/dockerfile_test/dockerfile1 -t test/centos:1.0 .
# . 表示当前目录作为构建上下文,注意不要忘记
- 启动容器,可以看到生成容器时挂载的两个数据卷目录 volume01 和 volume02
- 查看该容器的详细信息,可以看到挂载的两个匿名挂载的数据卷(生成在随机目录里)
- 重新进入该容器的其中一个数据卷文件夹中,创建一个新文件
- 退出容器并转到第4步中查询到的数据卷挂载目录下,发现数据被同步
6.3.1 练习:构建自己的 ubantu
编写 dockerfile 的文件
通过该文件构建镜像
docker build -f /data1/lsr/dockerfile_test/dockerfile1 -t myubuntu:0.1 .
docker build -f dockerfile文件路径 -t 镜像名:版本号 .
构建成功启动容器并验证 vim 是否安装成功,发现 vim 可正常使用,且工作目录更改为 /usr/local
6.3.2 Docker history 查看镜像构建历史信息
6.4 拉取镜像与运行容器
docker pull [用户名/DockerHub镜像名称]
docker run [镜像名]
7. 容器数据卷(Volume)
容器数据卷(Container Data Volume)是容器技术(如 Docker)中用于实现数据持久化存储、跨容器共享数据的核心机制。它允许将容器内的数据独立存储在宿主机或外部存储中,避免因容器重启、删除导致数据丢失,同时支持多个容器之间的数据同步。
docker volume COMMAND
Commands:
create
创建一个卷
inspect
展示卷的细节
ls
卷列表
prune
移除当地未使用的卷
rm
移除卷
7.1 命名卷 / 命名挂载
- 特点:
- 由 Docker 自动管理宿主机存储路径(默认位于 /var/lib/docker/volumes/),无需手动指定宿主机路径。
- 支持卷驱动(Volume Driver),可扩展至云存储(如 AWS EBS、阿里云 OSS)或分布式存储(如 NFS)。
- 数据隔离性好,适合生产环境,便于统一备份和迁移。
- 操作示例
# 创建命名卷
docker volume create my-vol
# 运行容器并挂载命名卷(容器内路径:/app/data)
docker run -d -v my-vol:/app/data nginx
# 查看命名卷详情(宿主机实际存储路径)
docker volume inspect my-vol
7.2 匿名卷 / 匿名挂载
- 特点:由 Docker 自动生成随机名称,通常用于临时存储或一次性数据。
docker run -v /container/path ...
# 匿名卷(省略名称)
命名挂载
匿名挂载
7.3 命名卷 VS 匿名卷
7.4 绑定挂载(Bind Mount)
- 特点:
- 直接挂载宿主机本地路径或文件到容器中,灵活性高但依赖宿主机文件系统。
- 适合开发场景(如本地代码实时同步到容器),但不支持跨主机共享,且需手动管理宿主机路径权限。
- 操作示例:
- #挂载宿主机路径 /data1/lsr/test 到容器的 /home 路径
docker run -it -v /data1/lsr/test:/home nginx
# -v 参数绑定挂载- 查看容器进程
docker inspect 02ba2d57f12e
# 查看该容器源数据,发现已经完成容器与主机的绑定挂载
- 测试,在容器中添加新文件,发现同一时间主机中也会增加该新增的文件
同样的,在主机中添加或修改文件,也可同步到容器中去,不管容器是否在运行
- 设置容器权限
容器内只读,只能通过宿主机修改:docker run -it -v /data1/lsr/test:/home:ro nginx
容器可读也可写:docker run -it -v /data1/lsr/test:/home:rw nginx
7.5 练习 Mysql 数据持久化
docker run -d -p 3310:3306 -v /data1/lsr/mysql/conf:/etc/mysql/conf.d -v /data1/lsr/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=2020 --name mysql01 mysql
#-d 后台运行、-p 暴露端口将3310和容器内3306映射、-v 绑定挂载数据卷,可挂载多个 、-e 配置环境,设置数据库密码
去数据库中检验连接成功,
新建一个数据库ronghaha,可分别从容器中以及主机中查看到相关数据
8. 数据卷容器
多个容器间如何同步数据
实战
- 创建一个新容器 docker01,创建后 ctrl + P + Q 容器不停止退回到主机
- 再创建一个 新容器 docker02 并于 docker01 进行挂载
- 在 docker01 的 volume1 目录中添加一个新文件 docker01,发现 docker02 的 volume1 的数据也会同步,反之在 修改 docker02 的 volume2 2,发现 docker01 的 volume2 的数据也会同步
docker02 中新增 docker02 文件
docker01 同步更新数据
- 删掉容器 docker01,发现 docker02 中的数据不变
多个 mysql 实现数据共享(两种方法)
docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=2020 --name mysql01 mysql
docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=2020 --name mysql02 --volumes-from mysql01 mysql
创作不易,求点赞,求收藏呀|ू・ω・` )