容器数据卷管理与自定义镜像发布实践
容器数据持久化与共享机制
Docker 的核心理念是将应用及其运行环境打包为镜像,但容器内部的数据在容器销毁后会丢失。为实现数据持久化,需将数据存储于容器外部的宿主机文件系统中。通过数据卷(Volume)技术,可实现容器间的数据共享与同步。
数据卷本质上是一种目录挂载机制,将容器内的指定路径映射到宿主机的物理路径上,从而保证即使容器被删除或重启,数据依然保留。
挂载方式一:命令行直接挂载
使用 -v 参数进行挂载,语法如下:
docker run -it -v <宿主机路径>:<容器内路径> <镜像名>
示例:将本地 /home/ceshi 挂载至容器内的 /home 目录:
docker run -it --name centos01 -v /home/ceshi:/home centos:7 /bin/bash
在此容器中任意增删文件,宿主机目录会实时同步。容器停止后,宿主机上的数据修改仍可在容器重启时生效,支持双向同步。
挂载类型包括:
- 匿名挂载:`-v /container/path` —— 宿主机路径由 Docker 自动分配
- 具名挂载:`-v volume_name:/container/path` —— 为卷命名便于管理
- 权限控制:可在路径后添加
:ro(只读)或:rw(读写)限制访问权限 - 指定路径挂载:`-v /host/path:/container/path` —— 显式绑定路径
实战:MySQL 数据持久化部署
配置 MySQL 容器并挂载数据目录和配置文件:
docker run -d \
-v /home/mysql/conf:/etc/mysql/conf.d \
-v /home/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root \
--name mysql03 \
mysql:5.7
可通过 Navicat 等工具连接 localhost:3306 验证数据库是否正常创建,并确认数据已持久化至宿主机。
具名与匿名卷管理
匿名卷生成的名称为随机字符串,不利于后期维护。建议使用具名挂载:
docker run -d --name tomcat02 -v my_volume:/etc/nginx nginx
查看卷的具体路径:
docker volume inspect my_volume
输出将显示该卷在宿主机中的实际位置。
方式二:通过 Dockerfile 实现挂载
在构建镜像时定义数据卷,使用 VOLUME 指令:
FROM mysql
VOLUME ["/volume01", "/volume02"]
CMD echo "---end---"
CMD /bin/bash
构建镜像:
docker build -f /home/myvolume/dockerfile1 -t sxf/mysql:1.0 .
启动容器后进入,使用 ls -l 可见两个挂载点。在这些目录中创建文件,再通过 docker inspect <container_id> 查看其对应宿主机路径,验证数据同步。
容器间数据共享:基于 Volume-From
通过 --volumes-from 实现容器之间的数据继承:
docker run --name parent_container -v /data:/shared_data centos:7
docker run -it --name child_container --volumes-from parent_container centos:7
子容器会继承父容器的所有数据卷。只要任一容器仍在使用数据,即使其他容器被删除,数据依然有效。
多实例共享场景示例:
docker run --name mysql01 -e MYSQL_ROOT_PASSWORD=root -d -p 8080:3306 -v /data/mysql:/var/lib/mysql mysql:5.7
docker run --name mysql02 -e MYSQL_ROOT_PASSWORD=root -d -p 8081:3306 --volumes-from mysql01 mysql:5.7
两个 MySQL 实例共享同一数据卷,实现数据一致性。
Dockerfile 构建自定义镜像
Dockerfile 是用于自动化构建镜像的脚本文件,遵循以下流程:
- 编写 Dockerfile
- 使用
docker build构建镜像 - 使用
docker run启动容器 - 使用
docker push发布镜像
Dockerfile 常用指令说明
| 指令 | 功能 | 备注 |
|---|---|---|
FROM | 指定基础镜像 | 必须第一行 |
MAINTAINER | 作者信息 | 已弃用,推荐使用 LABEL |
RUN | 构建时执行命令 | 支持 shell 形式或 JSON 数组形式 |
COPY | 复制文件到镜像 | 类似 docker cp |
ADD | 复制文件并自动解压或处理 URL | 优于 COPY,但安全性略低 |
WORKDIR | 设置工作目录 | 可多次使用,相对路径基于前一个 |
VOLUME | 声明数据卷 | 构建时定义,运行时通过 -v 映射 |
EXPOSE | 暴露端口 | 仅文档作用,不实际开放 |
CMD | 容器启动默认命令 | 可被 docker run 覆盖 |
ENTRYPOINT | 容器启动执行的主命令 | 配合 CMD 可传参 |
ONBUILD | 被继承时触发的命令 | 用于构建链 |
USER | 指定运行用户 | 避免以 root 运行 |
ENV | 设置环境变量 | 如 ENV MYPATH /home/app |
CMD 与 ENTRYPOINT 协同使用
当两者同时存在时:
- 若
ENTRYPOINT为非 JSON 格式,则CMD无效,仅使用ENTRYPOINT命令 - 若
ENTRYPOINT为 JSON 数组格式,CMD将作为参数拼接:
ENTRYPOINT ["nginx", "-c"]
CMD ["/etc/nginx/nginx.conf"]
最终等价于:nginx -c /etc/nginx/nginx.conf
自定义镜像实践
案例1:定制 CentOS 镜像
FROM centos
MAINTAINER YOUNG111@COM
ENV MYPATH /home/local
WORKDIR $MYPATH
RUN yum -y install vim net-tools
EXPOSE 8080
CMD echo $MYPATH
CMD echo "end-----"
CMD /bin/bash
构建命令:
docker build -f /home/dockerfile -t mycentos:1.0 .
案例2:自动创建测试文件
FROM centos
MAINTAINER sxf
ENV MYPTH /home/test
RUN mkdir $MYPTH
RUN touch $MYPTH/test.txt
RUN yum -y install vim net-tools
案例3:构建 Tomcat 镜像(含 JDK)
FROM centos
MAINTAINER sxf
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u11-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.22.tar.gz /usr/local/
RUN yum -y install vim net-tools
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_11
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.22
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.22/logs/catalina.out
运行容器:
docker run -d -p 9090:8080 --name sxf \
-v /home/sxf/build/tomcat/test:/usr/local/apache-tomcat-9.0.22/webapps/test \
-v /home/sxf/build/tomcat/tomcatlogs:/usr/local/apache-tomcat-9.0.22/logs \
<image_id>
在宿主机的 test 目录中添加 JSP 和 XML 文件,即可通过浏览器访问 http://localhost:9090/test 测试服务。
镜像发布策略
发布至 Docker Hub
- 注册 Docker Hub 账号
- 登录本地 Docker 客户端:
- 打标签并推送:
docker login -u <username>
docker tag <image_id> <username>/<repo_name>:<tag>
docker push <username>/<repo_name>:<tag>
发布至阿里云容器镜像仓库
- 在阿里云创建镜像仓库与命名空间
- 按指引操作:
docker tag <image_id> registry.cn-hangzhou.aliyuncs.com/<your_namespace>/<repo_name>:<version>
docker login --username=your_account registry.cn-hangzhou.aliyuncs.com
docker push registry.cn-hangzhou.aliyuncs.com/<your_namespace>/<repo_name>:<version>
私有镜像仓库搭建(Registry)
- 拉取 Registry 镜像:
- 运行私有仓库:
- 提交镜像至私仓:
- 打标签并推送:
- 验证推送结果:
docker pull registry
docker run -d -p 5000:5000 \
-v /opt/registry:/var/lib/registry \
--privileged=true \
registry
docker commit -m "Add web app" -a "admin" <container_id> myapp:v1.0
docker tag myapp:v1.0 localhost:5000/myapp:v1.0
docker push localhost:5000/myapp:v1.0
curl -XGET http://localhost:5000/v2/_catalog
注意:Docker 默认禁止向非 HTTPS 仓库推送。需在 /etc/docker/daemon.json 中添加:
{
"registry-mirrors": ["https://mirror.example.com"],
"insecure-registries": ["localhost:5000"]
}
修改后重启 Docker 服务以生效。