之前我们有讲过 Docker 核心原理(Namespace/Cgroups/UnionFS)如未阅读可查看老王linux-进阶-容器底层原理,namespace、cgroup、chroot、overlayfs 核心,基于此本篇探讨一下实际的应用,针对Compose+网络+数据卷+镜像构建几个方面进行阐述。
一、Docker Compose:多容器一键启停
Docker Compose 是 Docker 官方提供的「多容器管理工具」,核心作用:用一个配置文件(yaml),定义多个容器的启动参数、依赖关系,一键启动/停止所有容器。
1. Linux 安装 Docker Compose
需提前安装Docker并保证服务为运行状态:
bash# 下载 Compose(适用于所有 Linux 系统)curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose# 赋权(必须执行,否则无法运行)chmod +x /usr/local/bin/docker-compose# 验证安装成功docker-compose --version
2. 用 Compose 启动 Nginx+MySQL+Redis
第一步:创建目录
bash# 创建 compose 工作目录mkdir -p /opt/docker-compose/democd /opt/docker-compose/demo
第二步:创建 docker-compose.yml
yaml# 新建并编辑配置文件vim docker-compose.yml# 粘贴以下内容(直接复制,修改密码即可)version: '3' # Compose 版本,和 Docker 版本匹配(不用改)services:# 1. Nginx 容器nginx:image: nginx:latest # 镜像版本container_name: demo-nginx # 容器名ports:- "80:80" # 端口映射(宿主机80 → 容器80)volumes:- ./nginx/html:/usr/share/nginx/html # 数据卷挂载(后面讲)restart: always # 开机自启,容器异常自动重启networks:- demo-network # 加入自定义网络(容器间通信)# 2. MySQL 容器mysql:image: mysql:8.0 # 镜像版本(推荐8.0,稳定)container_name: demo-mysqlports:- "3306:3306"environment:- MYSQL_ROOT_PASSWORD=123456 # root 密码(改成你的)- MYSQL_DATABASE=demo_db # 自动创建数据库volumes:- ./mysql/data:/var/lib/mysql # 数据持久化restart: alwaysnetworks:- demo-network# 3. Redis 容器redis:image: redis:latestcontainer_name: demo-redisports:- "6379:6379"restart: alwaysnetworks:- demo-network# 自定义网络(让三个容器在同一网络,可互相通信)networks:demo-network:driver: bridge
第三步:一键启动所有容器
bash# 在 docker-compose.yml 所在目录执行docker-compose up -d# 查看启动状态docker-compose ps# 停止所有容器(如需)docker-compose down# 停止并删除数据卷(如需,谨慎使用)docker-compose down -v
执行 docker-compose up -d 后,3 个容器会自动启动,且互相能通信(比如 Nginx 能访问 MySQL、Redis)。
3. Compose 常用命令
bashdocker-compose up -d # 后台启动所有容器docker-compose ps # 查看当前 Compose 管理的容器docker-compose logs # 查看所有容器日志docker-compose logs -f 容器名 # 实时查看某个容器日志docker-compose stop # 停止所有容器(不删除)docker-compose start # 启动已停止的容器docker-compose restart # 重启所有容器docker-compose down # 停止并删除容器(不删数据卷)docker-compose down -v # 停止并删除容器+数据卷
注意点:
•配置文件必须叫docker-compose.yml(大小写敏感,不能改);
•执行命令时,必须在配置文件所在目录(否则会报错“找不到配置文件”);
•MySQL 密码、端口映射要提前规划,避免和宿主机其他服务冲突。
二、Docker 数据卷:容器数据持久化
在 MySQL 容器里创建了数据库,删除容器后,数据库就没了——这在工作中是致命的。Docker 数据卷(Volume)的核心作用:将容器内的目录,挂载到宿主机的目录,实现数据持久化(容器删了,宿主机数据还在)。
1. 数据卷的 3 种挂载方式
方式 1:绑定挂载
就是我们 Compose 配置里用的方式,直接指定宿主机目录 → 容器目录:
bash# 示例:启动 MySQL,挂载宿主机 /opt/mysql/data 到容器 /var/lib/mysqldocker run -d \--name mysql \-p 3306:3306 \-v /opt/mysql/data:/var/lib/mysql \ # 绑定挂载-e MYSQL_ROOT_PASSWORD=123456 \mysql:8.0
方式 2:匿名卷
bash# 只写容器目录,不写宿主机目录,Docker 会自动生成宿主机目录docker run -d \--name nginx \-v /usr/share/nginx/html \ # 匿名卷nginx
缺点:宿主机目录是随机生成的,不方便管理,不推荐生产环境使用。
方式 3:命名卷
先创建命名卷,再挂载,可重复使用,适合多容器共享数据,适合生产环境使用。
bash# 1. 创建命名卷docker volume create mysql-data# 2. 挂载命名卷到容器docker run -d \--name mysql \-p 3306:3306 \-v mysql-data:/var/lib/mysql \ # 挂载命名卷-e MYSQL_ROOT_PASSWORD=123456 \mysql:8.0# 查看所有命名卷docker volume ls# 查看命名卷详细信息(比如挂载路径)docker volume inspect mysql-data
2. 数据卷备份与恢复
备份(以 MySQL 命名卷为例)
bash# 备份命名卷 mysql-data 到 /opt/backup/mysql-backup.tar.gzdocker run --rm \-v mysql-data:/source \ # 挂载要备份的命名卷-v /opt/backup:/backup \ # 挂载宿主机备份目录busybox \tar -zcvf /backup/mysql-backup.tar.gz /source
恢复(恢复到新的命名卷)
bash# 1. 创建新的命名卷docker volume create mysql-data-new# 2. 恢复备份文件到新命名卷docker run --rm \-v mysql-data-new:/target \ # 新命名卷-v /opt/backup:/backup \ # 备份文件所在目录busybox \sh -c "tar -zxvf /backup/mysql-backup.tar.gz -C /target --strip-components 1"
注意点
•挂载时,宿主机目录如果不存在,Docker 会自动创建(但权限可能有问题,建议提前手动创建);
•Linux 下,挂载目录权限要注意(比如 MySQL 容器需要 777 权限,可执行 chmod 777 /opt/mysql/data);
•不要挂载宿主机的重要目录(比如 /root、/etc),避免误操作导致系统故障。
三、Docker 网络:容器之间怎么通信?
默认情况下,Docker 会创建一个「桥接网络」(bridge),所有容器默认加入这个网络,可通过「容器名」互相通信(不用记 IP)。例如,我们用 Compose 启动的 Nginx、MySQL、Redis,都在 demo-network 网络里,Nginx 容器可以直接通过mysql(容器名)访问 MySQL 服务,不用写 MySQL 的 IP。
1. Docker 网络的 4 种类型
•bridge(桥接网络):默认网络,容器之间可通信,也能访问宿主机/外网;
•host(主机网络):容器直接使用宿主机的网络,没有端口映射(适合需要高性能、无端口冲突的场景);
•none(无网络):容器没有网络,只能本地访问;
•overlay(叠加网络):用于多台宿主机之间的容器通信(K8s常用)。
2. 网络常用操作命令
bash# 查看所有 Docker 网络docker network ls# 创建自定义桥接网络(推荐,隔离性更好)docker network create my-network# 启动容器时,加入自定义网络docker run -d --name nginx --network my-network nginx# 查看网络详情(比如包含哪些容器)docker network inspect my-network# 容器加入已存在的网络docker network connect my-network mysql# 容器退出网络docker network disconnect my-network mysql# 删除网络(必须先停止/删除该网络下的所有容器)docker network rm my-network
3. 容器之间通信测试
bash# 1. 启动两个容器,加入同一个网络docker network create test-networkdocker run -d --name nginx-test --network test-network nginxdocker run -d --name redis-test --network test-network redis# 2. 进入 nginx-test 容器,访问 redis-testdocker exec -it nginx-test /bin/bash# 3. 在 nginx 容器内,ping redis-test(能 ping 通,说明通信正常)ping redis-test# 4. 也可以访问 redis 端口(6379)telnet redis-test 6379
四、自定义镜像构建
Docker 官方镜像(Nginx、MySQL)虽然好用,但实际工作中,我们需要「自定义镜像」:比如在 Nginx 镜像里加入自己的配置文件、在 Python 镜像里安装依赖包。使用Dockerfile(一个文本文件,定义镜像的构建步骤),通过docker build命令构建镜像。
1. 构建自定义 Nginx 镜像
第一步:创建 Dockerfile 和相关文件
bash# 1. 创建工作目录mkdir -p /opt/docker-build/nginxcd /opt/docker-build/nginx# 2. 创建自定义 Nginx 配置文件(nginx.conf)vim nginx.conf# 粘贴以下简单配置(可根据需求修改)server {listen 80;server_name localhost;location / {root /usr/share/nginx/html;index index.html;}}# 3. 创建 index.html(自定义首页)echo "我的自定义 Nginx 镜像" > html/index.html# 4. 创建 Dockerfile(核心文件)vim Dockerfile
第二步:编写 Dockerfile
dockerfile# 1. 基础镜像(必须有,从官方镜像继承)FROM nginx:latest# 2. 维护者信息(可选,方便后期维护)MAINTAINER XXX <xxx@xxx.com># 3. 将本地的 nginx.conf 复制到容器内的配置目录COPY nginx.conf /etc/nginx/conf.d/default.conf# 4. 将本地的 html 目录复制到容器内的网页目录COPY html /usr/share/nginx/html# 5. 暴露 80 端口(可选,只是声明端口,不实际映射)EXPOSE 80# 6. 启动 Nginx 命令(必须有,启动容器时执行)CMD ["nginx", "-g", "daemon off;"]
第三步:构建镜像
bash# 构建镜像(-t 给镜像打标签,格式:名称:版本)docker build -t my-nginx:v1 .# 查看构建好的镜像docker images
注意:命令末尾的.不能少,表示“在当前目录寻找 Dockerfile”。
第四步:运行自定义镜像
bashdocker run -d \--name my-nginx \-p 8080:80 \my-nginx:v1
访问宿主机 IP:8080,就能看到我们自定义的首页(“我的自定义 Nginx 镜像”),构建成功
2. Dockerfile 常用指令
•FROM:指定基础镜像(必须是 Dockerfile 的第一行);
•COPY:将本地文件/目录复制到容器内;
•RUN:构建镜像时执行的命令(比如安装依赖、创建目录);
•EXPOSE:声明容器运行时暴露的端口;
•CMD:容器启动时执行的命令(只能有一个,多个会覆盖);
•ENV:设置环境变量(比如 ENV JAVA_HOME /usr/local/jdk)。
注意点
•Dockerfile 文件名必须是Dockerfile(大小写敏感,不能改);
•构建镜像时,当前目录不要有无关文件(会增加镜像体积),可创建.dockerignore文件,排除不需要的文件;
•基础镜像尽量选择官方镜像,更安全、更稳定,避免使用第三方不明镜像。
可以根据自己实际使用场景构建自定义镜像分享到评论区。