这篇文章来源于我自己搭建和调试 Docker Compose 时的各种实践和踩坑记录 是一点点摸索出来的经验总结;如果你发现有更好的做法 或者某些地方值得讨论 欢迎在评论区留言;一起把这些细节理顺 把 Compose 玩得更顺手;
目录结构
config/
├── docker-compose.yml ← 我们的核心我文件
├── .env.example ← 这个是分享的配置示例
├── .env ← 这个是我们自己本地的文件(port/username/password...)
├── Dockerfile ←帮你把 docker-compose.yml 和 .env.example 打包成一个镜像的
docker-compose.yml
version: "3.8" services: # MySQL mysql: image: mysql:8.0 container_name: mysql-nacos env_file: - .env environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} ports: - "3311:3306" volumes: - ./mysql-data:/var/lib/mysql networks: - config_network restart: always networks: config_network: driver: bridgeversion: "3.8":
这个可有可无这个是 Docker Compose v1/v2 时期的一个规范号从 Docker Compose V2 开始(现在所有 Docker Desktop 都是 V2) 现在已经被官方废弃了,写不写都行看个人习惯;
services(核心)
声明这个以后可以在这里面写你需要拉取的服务了;
这些属性都是什么?
mysql: image: mysql:8.0image
要运行的镜像 → 官方 MySQL 8.0;
container_name: mysql-nacoscontainer_name
你给容器取的名字 方便 docker ps 里识别;
env_file: - .envenv_file
从当前目录加载.env文件里的变量 比如密码、数据库名;
environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD}environment
把.env里面的变量注入到容器内部;
等于在容器里运行时自动执行:
MYSQL_ROOT_PASSWORD=你的密码
这些是 MySQL 官方环境变量 用来初始化数据库
ports: - "3311:3306"ports
把宿主机 → 容器的端口做映射
| 3311 | 3306 |
|---|---|
| 你本机访问 | 容器的 MySQL |
别人访问你的 MySQL:ip:3311
容器内部服务访问 MySQL:mysql:3306
volumes: - ./mysql-data:/var/lib/mysqlvolumes(数据挂载)
左边:你电脑上的mysql-data
右边:容器内 MySQL 数据目录
容器删了 数据不丢; MySQL 占用空间在宿主机 ;
networks: - config_networknetworks
让 mysql 和 其他的服务在同一个网络里可以互相访问
相当于给它们都加入了一个局域网
restart: alwaysrestart 策略
容器异常退出会自动重启
服务器重启后自动启动
.env
.env是 Docker Compose 运行时真正加载的环境变量文件
也就是说 compose 启动容器的时候依赖的所有变量,都从.env拿
.env里要写什么?
就是所有 Compose 里用到的${XXX}值, compose 里包含:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} SPRING_DATASOURCE_URL: ${NACOS_JDBC_URL} SPRING_DATASOURCE_USERNAME: ${NACOS_DB_USER} SPRING_DATASOURCE_PASSWORD: ${NACOS_DB_PASS}所以.env应该长这样
# MySQL MYSQL_ROOT_PASSWORD=你的root密码 MYSQL_DATABASE=你的数据库名 MYSQL_USER=你的用户名 MYSQL_PASSWORD=你的用户密码 # NACOS 使用 MySQL 连接 NACOS_JDBC_URL=jdbc:mysql://mysql-nacos:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai NACOS_DB_USER=你的数据库用户名 NACOS_DB_PASS=你的数据库密码.env.example
它是一个 示例环境变量文件 ;作用很简单:用来告诉别人 .env 应该怎么写、有哪些变量需要填;
真正运行 Compose 的时候 Docker 只认:
.env(默认)
或你手动指定的env_file
.env.example 不会被 Docker 读取 它就是给人看的模板文件;
| 文件 | 用途 |
|---|---|
.env | 真正执行的环境变量,自己本地用 |
.env.example | 提供给别人参考的“模板”,不包含敏感值 |
Dockerfile
dockerfile是什么?一句话:
Dockerfile = 告诉 Docker:我要怎么做一个镜像
dockerfile文件:
FROM nginx:latest WORKDIR /share COPY docker-compose.yml . COPY .env.example . CMD ["sh", "-c", "tar -czf - *"]它的作用就是
帮你把 docker-compose.yml 和 .env.example 打包成一个镜像,方便分享
Dockerfile 就像食谱:
FROM:基底
我选择了 nginx 镜像 仅仅是为了方便,本地就有nginx:latest,无需再去拉取 ,正常应该是为FROM alpine 但是这个需要从 Docker Hub 拉基础镜像,本地没 alpine,它就要从国外拉 ,这个就需要魔法了
这个时候就有人问了 博主博主 我没有nginx也没有魔法怎么办呢?我搜了一下可以替换成
FROM debian:stable-slim RUN apt-get update && apt-get install -y tar WORKDIR /share COPY docker-compose.yml . COPY .env.example . CMD ["sh", "-c", "tar -czf - *"]这个我没有试过 可以试试 如果不行也没有魔法的情况下就下个nginx试试吧 我把代码放在下面了
version: "3.8" services: # MySQL mysql: image: mysql:8.0 container_name: mysql-nacos env_file: - .env environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} ports: - "3311:3306" volumes: - ./mysql-data:/var/lib/mysql networks: - config_network restart: always # Nginx nginx: image: nginx:latest container_name: nginx ports: - "80:80" volumes: - ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf - ./nginx/conf.d:/etc/nginx/conf.d - ./nginx/html:/usr/share/nginx/html - ./nginx/log:/var/log/nginx networks: - config_network restart: always networks: config_network: driver: bridgeWORKDIR:在容器里工作目录
COPY:把你的文件塞进镜像里
CMD:运行容器时做什么(你这里是打包成 tar)
最终:
你自己写的文件 → 通过 Dockerfile → 变成镜像 → 推到 Docker Hub → 别人拉取你的 compose 镜像
构建镜像
登录
首先需要先登录我们的docker-hub
前往docker-hub登录
构建
登陆后本地执行命令:
docker build -t yourname/compose-share:1.0 .注意!这里是在目录config执行的(参考目录结构)这里的“.”指的是所在的这个文件夹
docker build -t 你docker-hub登陆的名字 / 你取的名字;
这个前面一定要是登录的名字 不然到时候push上去会有认证的问题!
执行以后会弹出类似这样
此时你就构建成功了 !接下来就要执行:
docker login因为我们前面登陆过了的话就会自己去验证
弹出这样的也是登录成功了
推送
接下来我们执行推送上去的命令
docker push yourname/compose-share:1.0执行后弹出
就是推上去成功了
如何查看?
点击前往docker-hub查看
打开→我的中心
这里可以查看我们上传的所有的镜像;
如何修改名字?
有人又问了:博主博主 我想改这个镜像的名字怎么办?
好问题!
依旧在我们的仓库内部打开
因为当前docker-hub不支持修改名字 那么我们就需要创建一个新的仓库
创建完了以后就给自己本地刚刚我们构建好的镜像重新打tag:
docker tag yourname/compose-share:1.0 yourname/compose-modify:1.0docker tag 你原来的compose文件构建的 你想要修改的名字;
docker push yourname/compose-modify:1.0直接推上去即可;
如何覆盖?
比如你更新了你的 docker-compose.yml 或 .env.example:
重新 build
docker build -t yourname/compose-share:1.0 .重新 push(直接覆盖)
docker push yourname/compose-share:1.0完成!Docker Hub 上的 1.0 就变成新版本了
总结:改文件 → build → push → 覆盖同名 tag → 完成更新
如何获取你的compose 文件
Linux / Mac
docker run --rm yourname/compose-share:1.0 > compose.tar.gz tar -xzf compose.tar.gzWindows PowerShell
docker run --rm yourname/compose-share:1.0 > compose.tar.gz tar -xzf compose.tar.gzWindows CMD
docker run --rm yourname/compose-share:1.0 > compose.tar.gz tar -xf compose.tar.gz执行完后,他们的目录里会出现:
docker-compose.yml
.env.example
因为我们已经加了Dockerfile所以不需要输出其他的命令了
结语
如果你能看到这里 真的非常感谢你的时间;希望这些实践经验能帮你少踩一些我踩过的坑;如果你有新的想法、遇到奇怪的问题、或想讨论更多 Compose 的玩法 随时欢迎在评论区交流;你的每一句反馈 都是推动我继续分享的动力;祝你部署顺利!