简介:这份《Docker容器技术-安装Docker-compose.pptx》面向正在学习Docker容器编排的运维工程师、开发人员及技术爱好者,重点解决Docker Compose安装方式不清晰、命令易混淆的痛点。PPT围绕Docker Compose简介、下载软件包方式安装、使用源码仓库方式安装三条主线展开,内容预览中包含具体安装命令、版本查看方法以及两种安装方式下docker-compose与docker compose命令写法的区别,适合初中级学习者对照实操、梳理安装流程。资源包共1个文件,为pptx演示文稿,大小263KB,内容精炼、结构紧凑,便于直接用于培训或自学场景。已有158人浏览学习。通过本PPT,读者可以理解Docker Compose的作用与适用场景,掌握软件包安装和源码仓库安装两种主流方式,并快速厘清不同安装方法对应的命令差异,减少因命令使用错误导致的部署失败问题。
1. Docker容器技术绕不开的一步:为什么你早晚要装 Docker-compose
只要接触过 Docker容器技术,早晚会遇到 Docker-compose 这个词。它不像 Docker Engine 那样负责真正跑容器,也不像 Docker Desktop 那样给你一套图形界面,它干的事情是把「一条一条命令启动多个容器」变成「一个配置文件里写清楚所有服务,然后一条命令全部拉起来」。对刚入门的人来说,装 Docker 本身不算难,真正让新手卡住的反而是 Docker-compose:要么是下载脚本找不到,要么是权限报错,要么是配置文件写好了却启动失败。这篇笔记就是要把这条常见路走通,从安装方式到字段配置,再到最典型的几个报错,适合正在配 MySQL、nginx、GitLab 这类多容器环境的运维和开发同学。
2. 理解 Docker-compose:它到底解决了 Docker 的什么问题
2.1 从 docker run 到 docker-compose.yml:多容器协作怎么省事
如果你只跑一个测试用的 Redis,docker run redis:7就够了。但到了真实环境,事情会变成这样:要拉一个 MySQL,端口要映射好,账号密码要传进去;要拉一个后端服务,先把代码打包成镜像,再把环境变量传进去;还要拉一个 nginx,把前端静态文件挂载进去,同时把后端接口反向代理出去。如果你用 docker run 一条条敲,每次都要记那一长串参数,而且容器之间要用网络名互相访问,还得自己先docker network create,再在每条 run 命令里加--network。一个三个服务的项目,命令加起来能有一百多行。
Docker-compose 把这一整套动作声明式地写进一个 YAML 文件里。你在文件里定义服务名、镜像、端口、卷、环境变量、依赖关系,然后一个docker-compose up -d就能全部创建并启动。更关键的是,它天然会为这个项目创建一个独立的网络,服务名就是容器间的访问地址。后面想加一个服务,就改 YAML 文件,而不是去翻命令历史。这个思路很接近我们做工程的习惯:把复杂操作变成可读、可版本化的配置文件,而不是依赖人脑记忆和 shell 历史。我也见过团队用 Makefile 来封装,但 YAML 的声明式写法比 shell 脚本更容易让后端和前端同学一起看懂、一起改。
2.2 docker run、docker-compose、Kubernetes 怎么选
很多新人会问:有了 compose,还需要 Kubernetes 吗?两者解决的问题并不同。如果你只有一台机器,要跑 5 到 8 个互相配合的容器,docker-compose 是最合适的选择,它没有 etcd、operator 这些概念,模型就是「服务 + 容器」,上手成本低。Kubernetes 解决的是跨多台机器、大规模编排、自动伸缩、滚动更新这些复杂场景,对应的学习成本也高得多,光是一个 Pod 和 Deployment 的区别就能把人绕晕。
我的建议很简单:单机或小集群,就用 docker-compose;规模大到需要多主机调度,或者团队要求统一的发布平台,再考虑 Kubernetes。还有一个中间选项是 Docker Swarm,它和 compose 文件几乎兼容,但这些年发展节奏明显放缓,社区热度也不如 Kubernetes。以我常用的部署方式来看,一台 8G 内存的开发服务器上扔十几个容器,compose 完全吃得消,而且排错路径短很多——docker-compose logs一下就看到日志了,不用到处找监控面板。所以新人没必要一上来就啃 Kubernetes,把 compose 用透,已经能解决绝大多数日常部署问题。
2.3 Compose V2 和 V1:版本概念理清楚
还有个容易混淆的点是 compose 的版本号。长期维护的机器上,两条命令都存在过:老的是docker-compose(带横杠),新的是docker compose(空格)。Docker Compose V2 是作为 Docker CLI 插件发布的,从 Docker Engine 20.10 开始可以直接通过插件方式安装,而更老的 V1 则是一个独立 Python 脚本。2023 年年中开始,Docker 官方明确不再为 V1 提供支持,很多 Linux 发行版的 repo 里也逐渐不再默认提供docker-compose这个包。
所以你在搜索框里看到的各种报错要分清楚:如果是docker-compose: command not found,那是没装;如果是docker-compose: error while loading shared libraries: libz.so.1,那是老版本二进制在缺系统库,换官方插件方式通常能直接解决。我在下文给出的安装步骤也是基于「二进制文件放到 /usr/local/bin」或「官方插件放到 ~/.docker/cli-plugins」这两种做法,两者都能把你带到能用的状态,只是后续升级方式略有不同——二进制方式就是下载替换,插件方式则可以通过包管理器或手动覆盖。
3. Linux 上装 Docker-compose:两种主流方法对比
3.1 官方二进制下载方式:直接可用但要注意架构
最常见的中文教程推荐做法,是去 GitHub 的 docker/compose 仓库 release 页面下载对应的二进制文件,放到/usr/local/bin/docker-compose并赋予执行权限。这条路径的优点是步骤少、不依赖包管理器,缺点是 GitHub 下载速度在国外网络环境尚可、在国内经常超时。另外还有一个已经被踩过多次的坑:下载时没注意 CPU 架构,在 ARM 机器上下载了 x86_64 版本,结果运行直接报Exec format error。判断架构用uname -m,如果是aarch64,就要选aarch64后缀的文件;如果是x86_64,选x86_64后缀。
整套命令执行下来大概是这样:
# 先确认当前系统的 CPU 架构 uname -m # 下载 docker-compose 二进制文件(示例为 linux x86_64 版本) sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose # 赋予可执行权限 sudo chmod +x /usr/local/bin/docker-compose # 验证版本 docker-compose --version这个安装方式的逻辑就是把 compose 当作一个普通程序放进系统 PATH 里,shell 才找得到它。curl -L里的-L是跟随 GitHub release 页面的重定向,不加的话很容易下载到一个只有几十字节的 HTML 页面,然后出现docker-compose: cannot execute binary file的报错。还有一点要留意:latest这种写法在脚本里虽然方便,但生产环境不建议一直用它,因为我遇到过两次 release 版本行为有变化、配置文件的兼容性出现微妙差异的情况,固定版本号更稳妥,比如下载v2.27.0这种带具体版本号的资源。
3.2 插件方式安装:和 Docker Engine 配合更顺手
如果你用的是 Docker Engine 20.10 以上的版本,我其实更推荐把 compose 装成 Docker CLI 插件。装上之后,你可以用docker compose(空格)来执行命令,这样 compose 会跟着 Docker CLI 一起工作,config 命令的补全、环境变量继承等行为都比较一致。插件要放在~/.docker/cli-plugins/docker-compose或/usr/local/lib/docker/cli-plugins/docker-compose这两个目录之一,Docker CLI 启动时会自动扫描这些目录。
# 创建插件目录 mkdir -p ~/.docker/cli-plugins # 下载 docker-compose 插件文件 sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64" -o ~/.docker/cli-plugins/docker-compose # 赋予执行权限 sudo chmod +x ~/.docker/cli-plugins/docker-compose # 验证是否能被 docker 发现 docker compose version这段流程和二进制安装的区别就在目录上:一个文件在系统级 PATH 下,另一个在 Docker CLI 专有插件目录里。如果验证时发现docker compose version报了unknown command,先看文件权限对不对,再看文件是不是 x86 和 ARM 搞混了,最后看看~/.docker/cli-plugins目录是不是被设置了奇怪的权限。从维护角度看,插件方式的好处是团队里统一用docker compose命令,后面如果要接 Docker Desktop 的上下文管理,也不会有命令名混乱的问题。
3.3 镜像加速器与两分钟验证命令
不管哪种安装方式,装完之后动手写第一个 compose 文件前,建议顺手配一下镜像加速器。容器技术在拉取公开镜像时会走 Docker Hub,而在国内网络环境下 Docker Hub 的连接经常会出现超时或断流,现象就是docker pull卡在waiting状态或反复重试。官方也给了配置 registry mirrors 的机制,在/etc/docker/daemon.json里加一段配置即可:先sudo mkdir -p /etc/docker,然后写入镜像源地址,再sudo systemctl restart docker。我用的加速器地址一般是各云厂商提供的公共镜像源,你在国内云主机上部署时,通常也能在自己控制台里找到专属的加速器地址。
# 创建或编辑 daemon.json sudo vi /etc/docker/daemon.json # 写入内容: # { # "registry-mirrors": ["https://你的加速器地址"] # } # 重启 docker 服务让配置生效 sudo systemctl restart docker # 验证是否生效 docker info | grep -A 5 "Registry Mirrors"docker info里能看到Registry Mirrors段落,就说明配置生效了。这一步和 compose 安装没有直接关系,但它直接影响你后面的体验——如果镜像一直拉不下来,compose 文件写得再对也没用。
4. 编写 docker-compose.yml:核心字段与真实案例
4.1 最小可运行示例:nginx 加 MySQL
第一次上手 compose,建议不要直接照抄网上复杂的多服务模板。先写一个只有两三个服务的文件,把它跑通,再去加依赖关系、健康检查、网络别名这些进阶内容。我习惯先建一个目录,比如~/projects/nginx-mysql/,在这个目录下放docker-compose.yml,所有相对路径都基于这个目录解析。下面这是我能给的最简版本:
version: "3.8" services: nginx: image: nginx:1.25 container_name: web-nginx ports: - "8080:80" volumes: - ./html:/usr/share/nginx/html mysql: image: mysql:8.0 container_name: web-mysql environment: MYSQL_ROOT_PASSWORD: root123 MYSQL_DATABASE: appdb ports: - "3306:3306"这个文件里的version字段是 compose 文件格式的版本,不是 compose 命令的版本,常见的 3.x 系列在 V2 命令下都支持。services下每个键是一个服务名,服务名会同时成为 Docker 网络里的 DNS 名称,也就是说同一项目里后端服务可以用mysql:3306去访问数据库,而不是去查容器的 IP。ports里的写法是宿主机端口:容器端口,这里把 nginx 的 80 暴露到宿主机的 8080,是为了避免和宿主机可能已有的 nginx 冲突。volumes用相对路径./html把宿主机目录挂进容器,这样改静态文件不用重建镜像。
启动它只需两条命令:
# 在 docker-compose.yml 所在目录执行 docker-compose up -d # 查看运行状态和日志 docker-compose ps docker-compose logs -f nginxup -d的含义是「创建并后台启动」,日志会持续滚动到终端。第一次跑的时候必须看到两个容器的状态都是Up,而不是Exit。如果 MySQL 容器反复重启,十有八九是初始化 SQL 或权限问题,继续往后看第 5 章的排查思路。
4.2 网络、volume、环境变量:三个必懂的基础配置
真实项目里不可能像上面这样裸奔。至少有三类配置你绕不开:网络、命名卷、环境变量。网络场景典型的是「后端需要访问数据库、但数据库不对外暴露端口」——在 compose 的默认网络里,同一文件内所有服务天然可以通过服务名互相访问,即使不写任何networks字段。但如果你加了自定义网络段,就要注意每个服务都要声明挂到同一个网络,否则容器间会connection refused。我一般这样配置:
services: app: image: myapp:latest networks: - backend - frontend db: image: mysql:8.0 networks: - backend networks: backend: frontend:这段配置的核心是让 app 同时接入两个网络,而 db 只接入 backend。这样外部网段访问不了 db,只有同网络的 app 能连。命名卷和绑定挂载的区别也要说清:./html:/usr/share/nginx/html是绑定挂载,宿主机的文件变化会直接反映到容器里;而db-data:/var/lib/mysql是命名卷,数据实际存放在 Docker 管理的目录里,docker-compose down不会删除它,但如果你执行docker-compose down -v就会连数据一起删掉,这个-v我曾经就误加过一次,整个数据库文件直接没了一半。
环境变量方面,敏感信息不要直接写死在 YAML 里,尤其当文件要提交到 Git 仓库时。compose 支持从宿主机环境变量读取,比如${MYSQL_ROOT_PASSWORD},配合项目里的.env文件使用,.env文件默认会被 compose 读取,但最好加进.gitignore。
4.3 depends_on、restart、healthcheck:让服务按顺序健康启动
多服务编排最常见的翻车点在于启动顺序:后端服务在数据库还没有完成初始化时就尝试连接,结果连不上就崩了。depends_on能保证「先启动依赖的服务」,但注意它只是启动顺序上的等待,不保证「依赖服务已经可用」。MySQL 容器从启动到真正能接受连接,中间还有初始化过程,所以需要额外的手段。
services: app: image: myapp:latest depends_on: mysql: condition: service_healthy mysql: image: mysql:8.0 healthcheck: test: ["CMD-SHELL", "mysqladmin ping -h localhost -uroot -p$$MYSQL_ROOT_PASSWORD"] interval: 10s timeout: 5s retries: 5这段里两个细节要细看:depends_on在 V2 语法里支持condition字段,service_healthy表示等依赖服务健康检查通过后再启动本服务;healthcheck里的$$MYSQL_ROOT_PASSWORD写的是双美元符号,因为 compose 会先做一层变量替换,双美元转义成单美元给容器执行。interval是检查频率,timeout是单次检查的超时时间,retries是连续失败多少次判定为不健康。这几个参数决定了一个容器从启动到被确认为「可用」的时间窗口,对于数据库服务,我一般把 retries 调成 10,因为冷启动 MySQL 在机械盘上可能需要二十秒以上。
4.4 用 docker-compose 部署一个完整的 GitLab 社区版
这套组合我实际用过,适合作为综合练习。GitLab 依赖 PostgreSQL 和 Redis,用 compose 统一管理可以让整个部署过程变成「写一个文件 + 拉一次镜像」。这里用gitlab/gitlab-ce:latest这个镜像,挂载三个目录分别存配置、数据和日志,完整配置如下:
version: "3.8" services: gitlab: image: gitlab/gitlab-ce:latest container_name: gitlab restart: always hostname: gitlab.example.com environment: GITLAB_OMNIBUS_CONFIG: | external_url 'http://gitlab.example.com' gitlab_rails['gitlab_shell_ssh_port'] = 2222 ports: - "80:80" - "443:443" - "2222:22" volumes: - gitlab-config:/etc/gitlab - gitlab-logs:/var/log/gitlab - gitlab-data:/var/opt/gitlab volumes: gitlab-config: gitlab-logs: gitlab-data:GITLAB_OMNIBUS_CONFIG是 GitLab 官方镜像特有的配置入口,external_url决定了页面上展示的仓库地址,如果写错会导致 clone 地址不正确。三个命名卷分别持久化配置文件、日志和实际仓库数据,这样升级镜像时可以保留数据。启动后用docker-compose logs -f gitlab观察状态,看到"Running"或类似日志后,浏览器访问http://宿主机IP就能看到登录页。初次启动因为要初始化数据库和编译资源,慢是正常的,有的机器上要等三四分钟,别因为这期间页面打不开就觉得部署失败了。
5. Docker-compose 安装排错避坑:3 个高频坑的排查顺序
5.1 permission denied 一系:当前用户不在 docker 组
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock是新手最常撞见的报错。现象是docker-compose ps或docker ps都出现 permission denied,但sudo docker ps正常。原因是 Docker 守护进程默认以 root 权限监听 unix socket,普通用户不在docker用户组里,就没有权限访问。解决方式是把自己加入 docker 组,然后重新登录终端。
# 将当前用户加入 docker 组 sudo usermod -aG docker $USER # 重新登录 shell 组权限才生效 newgrp docker # 验证 docker ps这里有个容易忽略的点:usermod之后,已经打开的终端窗口不会自动获得新的组权限,必须退出重新登录或执行newgrp docker。另外如果是云服务器初始用户,比如 ubuntu 用户,也会遇到同样问题,不是只有 root 才报这个错。有人为了省事直接chmod 777 /var/run/docker.sock,这是个极度危险的操作,等于把 Docker 守护进程的完全控制权交给所有用户,千万别这么做。
5.2 libz.so.1 报错:老二进制包的系统库依赖
docker-compose: error while loading shared libraries: libz.so.1: failed to map segment from shared object这条报错,常见于老版本的docker-compose二进制在精简系统镜像或容器内运行的环境。现象是版本命令都打不出来,直接提示加载共享库失败。原因大概率是下载的二进制是旧版本(比如 1.29.x),它动态链接到了系统里的某些 .so 库,而当前系统缺这个库或版本不匹配。解决方法是换用官方最新插件方式安装,或者安装libz-dev/zlib1g这类依赖包。
# Debian/Ubuntu sudo apt update && sudo apt install -y zlib1g # 验证 docker-compose version如果补装库之后还在报错,那就别费劲找旧版本了,直接卸载旧二进制,改用第 3 章的插件方式重新装。旧版本 compose 的 Python 依赖链在 2023 年之后已经和 Docker Engine 的演进脱节,在比较新的内核和 glibc 环境下兼容性很脆弱。
5.3 Windows 上 Docker Desktop 虚拟化未开启
Windows 11 用户安装 Docker Desktop 时,最常见的一个坎是启动时提示virtualization support not detected或Docker Desktop failed to start because virtualisation support wasn't detected。现象是 Docker Desktop 一直停留在启动动画,过一会儿提示失败。原因有两类:一类是 BIOS 里虚拟化技术没打开,需要进固件设置开启 VT-x 或 AMD-V;另一类是 Windows 自带的虚拟机监控程序没启用,需要在「Windows 功能」里勾选「虚拟机平台」和「适用于 Linux 的 Windows 子系统」,然后重启系统。
# 以管理员身份运行 PowerShell,检查虚拟化状态 systeminfo | Select-String "Hyper-V" # 启用需要的 Windows 功能 Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-All Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux执行完一定要重启,然后重新打开 Docker Desktop。另外还有一条:如果本机装了 360、鲁大师之类的安全工具,有时候会拦截 Docker Desktop 创建虚拟网卡的行为,现象就是提示网络适配器无法启动。遇到这种情况先把安全工具退出,再启动 Docker Desktop,真的有不少用户是这么解决的——这算是一个比较偏的踩坑经验。
5.4 容器内访问 MySQL 失败:端口映射和绑定地址
访问容器内的 MySQL 失败也是个高频问题,直观现象是:宿主机用 Navicat 连接localhost:3306失败,或者别的容器连接mysql:3306失败。原因要分层排查:先看容器起来没有,docker-compose ps里状态是不是Up;然后看端口映射是否生效,docker-compose port mysql 3306会输出实际的宿主端口;最后看 MySQL 的 bind-address,容器内 MySQL 默认监听所有网卡,但也有镜像通过环境变量把 bind-address 写成 127.0.0.1 的情况,那样就只能本机访问,跨容器必然失败。
一个实际经验是:如果你要在宿主机上用 MySQL 客户端访问容器数据库,ports里不要写127.0.0.1:3306:3306这种绑定到回环地址的写法,否则局域网其他机器是连不上这个数据库的;反过来,如果只是为了开发调试,这个写法反而更安全,系统防火墙之外的机器看不到这个端口。这两者的取舍看场景,别统一照抄。
6. 让你的 compose 环境更好用:三个进阶习惯
6.1 用 docker-compose config 检查配置文件
写好的 YAML 文件直接up之前,建议先跑一遍docker-compose config,它会做两件事:把变量替换成实际值,并按顺序展示完整展开后的服务配置。这样能提前发现缩进错误、未知字段、变量未定义等问题,不用等容器创建到一半才报错。我在改动环境变量之后,都会先执行这个命令确认替换结果。如果文件里有敏感信息,docker-compose config会把变量值打出来,注意终端别被录屏。
# 检查变量替换结果 docker-compose config # 如果只想看某个服务 docker-compose config --services6.2 把固定版本写进镜像标签
这个习惯我用了一年多,带来的好处远比麻烦多。很多人直接写nginx:latest或者复用别人的mysql:latest,好处是省事,坏处是镜像发布方如果更新了 tag 指向,启动行为可能变化。尤其在团队协作环境里,要求「依赖可复现」就不能让镜像版本跟着 latest 跑。所以我的习惯是:第一次写完 compose 文件并验证成功后,把镜像标签固定成具体版本,比如mysql:8.0.36,并在文件里用注释记录「这个版本跑过,不要随便升」。
6.3 服务更新时用 down 和 rebuild 的边界
日常开发中,改了代码要重建镜像再启动服务,但这里有个容易翻车的点:docker-compose restart并不会重新构建镜像,它只是停容器再启容器,如果你改了 Dockerfile 或代码,必须docker-compose build之后再up -d,顺序反了会看着旧镜像一直跑。另外docker-compose down只会停容器,不会删镜像,也不会动命名卷里的数据,这一点掌握好,可以避免很多「数据没了」的恐慌。只有当你确认要清除所有数据时才要在down后面加-v,这个参数真的是没有后悔药的。
如果网络配置想彻底重建,down之后网络会被移除,下次up重新创建。这个机制也带来一个经验:固定 IP 这种配置不要写在 compose 文件里,除非你有充分理由,否则每次重建网络都可能让网络配置出问题。平时我改完配置的思路是:先docker-compose config检查,再docker-compose up -d让 compose 自动重建需要重建的容器,最后docker-compose logs -f看启动日志。这套流程走下来,基本能在两分钟内确认改动是否生效,也避免了「改了配置但没重启」的尴尬。希望这些从安装到排查再到进阶的经验,能帮你在这个方向上少踩几个坑。
本文还有配套的精品资源,点击获取