Docker实战笔记:从安装配置到镜像容器化部署全攻略
2026/9/15 19:55:00 网站建设 项目流程

我第一次被Docker“教育”,是在一次周末加班部署的时候。项目要上线,环境是CentOS 7,JDK、MySQL、Redis、Nginx一样一样手动装,装到一半发现版本不对,卸载重来,前后折腾了大半天。后来同事跟我说:“你试试把整个环境打个包,跑在容器里。”我心想这不就是个轻量虚拟机吗?结果真正用起来才发现,根本不是一回事。

这篇文章基本算是我多年Docker使用经验沉淀下来的一套笔记。网上流传的那份“狂神说Docker”笔记我一直留着,刚入门时就是跟着它跑通了第一个容器,非常感激;后来在生产环境踩了不少坑,我又在原笔记基础上补了大量实操细节和故障排查经验。今天全部分享出来,适合刚接触容器的新手,也适合已经用了一段时间、但没系统梳理过命令和原理的人。内容比较长,建议先收藏,遇到问题再回来翻。

先把我最核心的体会放在前面:Docker不难,难的是理解它的设计思想。一旦想明白“镜像只读、容器可写、数据靠卷、通信靠网络”这四句话,后面所有命令和配置都是顺水推舟。

1. 装好Docker这一关:Windows和Linux双平台避坑实录

装Docker看起来是最简单的一步,但“virtualization support not detected”和“Docker Desktop failed to start”这两个错误,常年霸占Docker相关搜索榜前列。问题不是Docker本身难装,而是前置条件太容易被忽略。

1.1 Windows装Docker Desktop前先确认虚拟化开关

Docker Desktop在Windows上有两种后端,老版本用Hyper-V,新版本默认走WSL2。不管哪一种,前提都是CPU虚拟化必须开启。很多人启动Docker Desktop后看到虚拟化报错,第一反应是重装,其实问题基本出在BIOS或Windows功能上。

排查步骤按这个顺序来:

  1. 打开任务管理器 → 性能 → CPU,看右下角“虚拟化”是否显示“已启用”。
  2. 如果显示“已禁用”,重启进BIOS,找到Intel Virtualization Technology或SVM Mode(AMD平台),设为Enabled。
  3. 确认BIOS没问题后,检查Windows功能里是否开启了“适用于Linux的Windows子系统”和“虚拟机平台”。路径是控制面板 → 程序 → 启用或关闭Windows功能。
  4. 如果用的是老版本Docker Desktop,还需要勾选“Hyper-V”,同时注意别和其他虚拟机软件抢资源。

有个很容易被忽略的细节:某些主板的BIOS虚拟化选项藏得很深,比如部分品牌台式机在Advanced → CPU Setup里,有的需要开机按F2而不是Del。实在找不到就直接用主板型号搜索“怎么开启VT”,别硬猜。

1.2 WSL2模式修复的最后一招

如果你确定BIOS和Windows功能都开了,Docker Desktop仍然报虚拟化问题,有一种常见情况是WSL2本身没装好。打开PowerShell(管理员),执行:

wsl --install wsl --set-default-version 2

然后重启电脑,再打开Docker Desktop。另外,老版本Windows 10跑WSL2会有一堆莫名其妙的问题,建议直接把系统升到较新版本,省心很多。

1.3 Ubuntu与CentOS的安装命令差别

Linux下安装Docker相对简单,但要注意“系统自带源里的版本”和“Docker官方源里的版本”是两个概念。

Ubuntu上很多教程直接让执行apt install docker.io,这个包确实能用,但版本往往落后。我更推荐用官方源安装:

sudo apt update sudo apt install ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

CentOS 7虽然官方已经不再维护,但存量机器还很多,升级到新版Docker用这套:

sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo yum install -y docker-ce docker-ce-cli containerd.io

装完以后有个习惯必须建立起来:Docker服务默认不会开机自启。所以每次配置完/etc/docker/daemon.json这类文件,记得用下面两条命令收尾:

sudo systemctl enable docker sudo systemctl start docker

1.4 权限报错的根源是用户组

很多Linux新手装完Docker,执行docker ps直接收到permission denied,原因很简单:docker命令需要root权限,而当前用户不在docker组里。解决办法不是每次都加sudo,而是把用户加进docker组:

sudo groupadd docker sudo usermod -aG docker $USER newgrp docker

这里必须提醒一句:能加入docker组的用户,基本等同于拥有root权限,因为Docker可以把宿主机任意目录挂载进容器。多人共用的生产服务器上,不要随便给普通用户加这个组。

2. 镜像和容器:这两个概念搞明白,Docker就入门了一半

2.1 菜谱和菜的关系

很多人一开始把Docker想象成虚拟机,这个类比害人不浅。虚拟机里装的是完整操作系统,每个虚拟机都是一台独立电脑;而Docker容器共享宿主机内核,它本质上只是一个隔离的进程运行环境。

我更愿意用菜谱和菜来打比方:

  • 镜像就是菜谱加半成品食材包,它是只读的,里面定义了环境的一切:装了什么系统、什么依赖、什么程序、启动命令是什么。
  • 容器就是照着菜谱做出来的一道菜,你可以往里面加料、改配置,但菜谱本身不会变。
  • 仓库就是大菜市场,里面有别人做好的各种菜谱,比如MySQL菜谱、Redis菜谱、Nginx菜谱。

用命令来解释更直观:

docker pull mysql:8.0 # 去仓库下载MySQL 8.0镜像 docker run -d --name mydb mysql:8.0 # 基于镜像创建并启动容器 docker ps # 查看运行中的容器 docker ps -a # 查看所有容器,包括已停止的 docker stop mydb # 停止容器 docker rm mydb # 删除容器 docker images # 查看本地所有镜像 docker rmi mysql:8.0 # 删除镜像

注意docker rm删除的是容器,docker rmi删除的是镜像,很多新手在这俩上面栽跟头。

2.2 镜像是分层的

镜像的另一个重要特性是分层(Layer)。你pull一个镜像的时候,输出里会显示很多层,每一层对应一个小改动。比如一个基于CentOS的镜像,底层是系统基础层,往上可能是JDK安装层,再往上才是你的应用jar包层。

分层最大的价值在于复用和节省空间。本地已经有一个CentOS基础层,再拉其他基于CentOS的镜像,基础层就不用重复下载。这也是Docker镜像比虚拟机文件小得多、启动速度快得多的根本原因。

2.3 镜像标签里的学问

镜像名后面的冒号是标签(tag),mysql:8.0mysql:latest是两回事。生产环境强烈建议固定tag,不要用latest。latest会随着官方更新变化,今天拉的和明天拉的可能是不同版本,等出了问题你根本不知道线上跑的到底是哪个版本。我见过不止一次因为latest导致MySQL大版本意外升级、配置文件不兼容的线上事故。

3. 拉镜像慢的解决方案:加速器配置与自建仓库

3.1 为什么直连Docker Hub经常超时

Docker Hub的镜像服务器在海外,国内网络环境下拉取大镜像经常出现进度条长时间不动、或者卡在等待状态。这个问题属于基础设施层面的问题,自己换DNS、重启网卡都解决不了。主流思路是给Docker配置镜像加速器,或者自建私有仓库。

3.2 daemon.json配置加速器

Docker守护进程会读取/etc/docker/daemon.json加载加速器配置,Windows则在Docker Desktop的Settings → Docker Engine里改同样格式的JSON:

{ "registry-mirrors": [ "https://docker.1ms.run", "https://docker.xuanyuan.me" ] }

保存后Linux执行systemctl restart docker,Windows重启Docker Desktop即可生效。

这里说明一下:加速器只对从Docker Hub拉取的公共镜像生效,对私有仓库和其他第三方仓库不生效。而且很多公共加速地址会变动,建议多配几个,失效了及时更换。

3.3 企业内网自建Registry

如果团队内部经常要分发同一个镜像,与其每个人各自去外网拉,不如搭一个内部镜像仓库。用极简的Docker Registry做演示:

docker run -d -p 5000:5000 --restart=always --name registry registry:2

推送和拉取方式:

docker tag mysql:8.0 192.168.1.100:5000/mysql:8.0 docker push 192.168.1.100:5000/mysql:8.0 docker pull 192.168.1.100:5000/mysql:8.0

默认情况下Registry走HTTP协议,而Docker守护进程只信任HTTPS的仓库,所以要在daemon.json里声明内网HTTP仓库:

{ "insecure-registries": ["192.168.1.100:5000"] }

自建仓库的价值不只是拉取快。生产环境里镜像内容可审计、版本可控,出问题可以快速回滚到上一个版本,这些在运维中比“拉得快”重要得多。

4. 数据持久化:容器删了不代表数据还在

4.1 容器是“用完即走”的

容器被删除后,容器内的所有数据也会随之消失,因为容器写入层本来就是临时的。这是设计思想,不是Bug——容器被定位成“无状态”的进程运行环境。但数据库、配置文件、日志这些必须有状态,所以Docker提供了卷(Volume)和绑定挂载(Bind Mount)两种持久化方式。

4.2 -v挂载和命名卷的区别

先看最简单的绑定挂载,把宿主机的一个目录映射进容器:

docker run -d --name mysql8 \ -p 3306:3306 \ -v /data/mysql:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ mysql:8.0

这里/data/mysql是宿主机目录,/var/lib/mysql是容器里MySQL的数据目录。容器删了,宿主机目录里的数据还在,下次重新run一个容器,把同一个目录挂载进去,数据就回来了。

命名卷(Named Volume)则是把目录托管给Docker管理,做有状态服务时更推荐:

docker volume create mysql_data docker run -d --name mysql8 \ -v mysql_data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123456 \ mysql:8.0

两者区别在于:绑定挂载的路径由你在宿主机指定,方便直接查看和备份;命名卷的路径由Docker管理,跨主机迁移时更规范。我生产环境的习惯是:数据库用命名卷,日志和应用配置用绑定挂载。

4.3 MySQL 8.0部署实例与字符集坑

热词里大家都在搜“docker安装mysql8.0并使用”,说明新手踩坑多。先给一套完整的运行命令:

docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD='Root@123' \ -e TZ=Asia/Shanghai \ -v mysql_data:/var/lib/mysql \ -v /etc/localtime:/etc/localtime:ro \ mysql:8.0

进容器测试连接:

docker exec -it mysql8 mysql -uroot -p

MySQL 8.0默认的认证插件是caching_sha2_password,老版本的Navicat连接会报认证失败。如果确实需要兼容老客户端,可以改认证方式:

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'Root@123'; FLUSH PRIVILEGES;

还有字符集问题。Docker官方MySQL镜像默认字符集可能是utf8mb4,但排序规则不一定符合预期,中文业务系统建议启动后执行SET NAMES utf8mb4,或在my.cnf里显式配置。

4.4 数据库备份与恢复

容器里的MySQL备份不用进容器,直接在宿主机用docker exec配合mysqldump:

docker exec mysql8 sh -c 'exec mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" --databases yourdb' > backup.sql

恢复:

cat backup.sql | docker exec -i mysql8 mysql -uroot -p

这里有个关键细节:备份要用sh -c 'exec ...'的形式,而不是直接docker exec mysqldump,这样能让mysqldump成为容器内的1号进程,避免shell残留导致备份不完整或命令挂起。我早期就因为这个吃过亏,备份出来的SQL缺了最后一段,恢复系统时才追悔莫及。

5. 容器网络:端口映射与跨容器通信

5.1 -p映射端口的本质

容器内部有独立的网络命名空间,宿主机要访问容器内的端口,必须通过端口映射。docker run -p 3306:3306意思是把宿主机的3306端口映射到容器的3306端口,左侧是宿主机端口,右侧是容器端口。

新手经常问:为什么改了容器里的端口,外面连不上?因为映射关系在创建容器时就固定了,要改端口映射只能删了容器重新run。Docker不是路由器,端口映射是一条不可热更新的规则。

5.2 自定义bridge网络才是容器互通的正解

默认情况下,容器通过名为bridge的默认网络互联,可以用IP互访,但IP会随容器重建而变化,不稳定。更推荐创建自定义bridge网络,让容器之间用容器名互相访问:

docker network create mynet docker run -d --name redis1 --network mynet redis:7 docker run -d --name redis2 --network mynet redis:7

在redis1容器里可以直接用redis2作为主机名连接。Docker内置的DNS会自动完成容器名到IP的解析,这是服务发现最简单的实现形态。

5.3 实战:Redis主从集群

热词里有“docker安装redis主从”,我分享一下标准做法。先建网络,再分别启动主从节点:

docker network create redis-net docker run -d --name redis-master \ --network redis-net \ -p 6379:6379 \ redis:7 redis-server --appendonly yes docker run -d --name redis-slave1 \ --network redis-net \ redis:7 redis-server --replicaof redis-master 6379

进入从节点检查状态:

docker exec -it redis-slave1 redis-cli info replication

看到role:slavemaster_link_status:up,说明主从正常。整个过程最关键的是--replicaof redis-master 6379里用了容器名而不是IP,如果写死IP,以后主节点重建、IP一变,从节点就会失联。这就是自定义网络相比IP直连的最大优势。

5.4 外部访问失败先查防火墙

端口映射配好了但外部访问不上,很多情况是宿主机防火墙拦截。CentOS 7常见的放行方式:

firewall-cmd --permanent --add-port=3306/tcp firewall-cmd --reload

如果是云服务器,还要去安全组放行端口。最典型的现象是“本机连得上、外部连不上”,第一反应应该是查安全组,而不是去容器里翻日志。

6. Docker Compose:多容器编排的正确打开方式

6.1 一条docker run解决不了的问题

一个典型Web项目,可能需要MySQL、Redis、Nginx、应用服务四个容器。如果都靠手敲docker run,命令又长又不直观,每次重建环境都要重新敲一遍。Compose的作用就是让容器编排变成“写配置文件 + 执行up”。

6.2 一个可直接套用的docker-compose.yml

以部署MySQL 8.0加Redis 7.0为例:

version: '3.8' services: mysql8: image: mysql:8.0 container_name: mysql8 restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: 'Root@123' TZ: 'Asia/Shanghai' ports: - "3306:3306" volumes: - mysql_data:/var/lib/mysql - ./conf/mysql:/etc/mysql/conf.d networks: - app-net redis: image: redis:7 container_name: redis7 restart: unless-stopped command: redis-server --appendonly yes --requirepass Redis@123 ports: - "6379:6379" volumes: - redis_data:/data networks: - app-net volumes: mysql_data: redis_data: networks: app-net: driver: bridge

启动命令:

docker compose up -d docker compose ps docker compose logs -f mysql8

新版Docker已内置compose子命令docker compose,老环境才需要单独安装docker-compose。如果提示找不到命令,用pip install docker-compose或安装docker-compose-plugin包。

6.3 restart策略要理解到位

restart: always不是“重启容器”的意思,而是“无论容器以什么方式退出,Docker守护进程都会把它拉起来”,除非明确docker stop。对于有状态服务,我建议用restart: unless-stopped。两者唯一差别在于:手动docker stop之后,unless-stopped不会自动拉起,而always会在Docker服务重启后又把它拉起来。这个区别在“故意停掉一个服务维护”的场景里非常重要。

6.4 敏感信息交给.env管理

compose文件里写明文密码,提交到Git仓库等于把数据库密码公之于众。生产环境至少用.env文件管理:

# .env MYSQL_ROOT_PASSWORD=ChangeMe123 REDIS_PASSWORD=ChangeMe456

compose文件里用${MYSQL_ROOT_PASSWORD}引用,然后在.gitignore里忽略.env。进一步可以上Docker Secrets或专门的密钥管理服务,但对中小团队来说,先做到.env不入库已经是很大进步。

多说一句:很多从GitHub拉下来的开源项目,比如Dify这种,代码里通常有一个.env.example模板文件,部署前第一步就是复制成.env再执行docker compose up -d。很多人部署失败,不是命令写错,而是漏了cp .env.example .env这一步。

7. 自己写Dockerfile,把项目变成镜像

7.1 核心指令速览

Dockerfile是构建镜像的配方文件。最常用的指令有这几个:

  • FROM:基础镜像,一切从这里开始
  • WORKDIR:设置工作目录
  • COPY:把文件复制进镜像
  • RUN:构建时执行的命令
  • EXPOSE:声明容器监听端口
  • ENV:设置环境变量
  • CMD/ENTRYPOINT:容器启动后的默认命令

以 Spring Boot 项目为例:

FROM eclipse-temurin:17-jdk WORKDIR /app COPY target/app.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]

构建:

docker build -t myapp:v1 .

7.2 多阶段构建瘦身

Java项目构建需要JDK和Maven,运行只需要JRE。如果只用一个基础镜像,构建产物里会混入大量编译器内容,镜像体积轻松上500MB。多阶段构建可以解决这个问题:

# 第一阶段:构建 FROM maven:3.9-eclipse-temurin-17 AS builder WORKDIR /build COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn package -DskipTests # 第二阶段:运行 FROM eclipse-temurin:17-jre WORKDIR /app COPY --from=builder /build/target/app.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]

构建完用docker images查看,运行镜像会小很多。瘦身不是洁癖,体积小的镜像拉取快、启动快、攻击面小,生产环境收益非常明显。

7.3 IDEA一键打包Docker镜像

热词里有“idea 打包docker镜像”,说明很多Java开发想省掉命令行构建的麻烦。IDEA的做法是:

  1. 在File → Settings → Build, Execution, Deployment → Docker里连接本机或远程Docker。
  2. 在运行配置里新建Dockerfile运行配置,指定Dockerfile路径和镜像名。
  3. 点击运行,IDEA自动完成build。

有一点注意:如果是远程Docker,IDEA构建时需要把上下文目录上传到远程服务器,项目大了会慢。这种情况更推荐在CI流水线里构建,本地只负责开发和推代码。

7.4 微服务部署的常见误区

“docker部署微服务项目”这个关键词很火。微服务容器化不是简单地把每个服务打成镜像就完事,还有服务发现、配置中心、网关、日志收集一堆问题要处理。如果只有四五个服务,用Compose加自定义网络就够;如果有几十个服务,就要考虑Kubernetes这类编排平台。但上手K8s之前,先把Docker本身的网络、卷、健康检查吃透,不然直接跳进K8s只会更晕。

8. Docker Desktop故障排查手册

8.1 “Failed to connect to the docker api at npipe”型错误

Windows上Docker Desktop突然连不上,报错信息出现npipe:////./pipe/dockerDesktopLinuxEngine,多半是Docker引擎挂了,不是Docker Desktop整体坏了。常见修复顺序:

  1. 右键Docker Desktop托盘图标,选择Restart。
  2. 不行就退出Docker Desktop,打开PowerShell执行wsl --shutdown,再重新启动。
  3. 再不行,在Settings → Troubleshoot里点Clean / Purge data,这会重置Docker的WSL发行版数据,一般能救回来,但也会清掉Docker Desktop默认卷里的数据。

如果你之前把数据都挂载到宿主机目录或命名卷里,第三步就没那么可怕。这也是我一直强调数据必须持久化的原因之一。

8.2 “unexpected EOF”类拉取中断

docker pull到一半报unexpected eof,基本是两种原因:网络不稳定导致传输中断,或者镜像加速器超时。处理手段是换一个更稳定的加速器,重新pull。大镜像本身就是分层下载的,中断后重新执行会续传已下载的层,不用太担心。

8.3 Docker磁盘占用爆炸

Docker用久了,Windows的C盘会被镜像和构建缓存占满。先看占用:

docker system df

清理:

docker system prune -a

这个命令会删掉所有未使用的镜像和构建缓存,执行前注意看输出确认没删错。我平时用更温和的组合:docker image prune -a清理无用镜像,docker builder prune清理构建缓存,按需执行,避免把还在用的镜像误删。

8.4 WSL2网络卡顿导致容器内DNS异常

另一种低频但很折磨人的情况是,容器里能ping通IP但解析不了域名,同时宿主机网络一切正常。这时候先怀疑WSL2的虚拟网络适配器卡死了。PowerShell执行wsl --shutdown,等几秒再启动Docker Desktop,绝大多数能恢复。如果频繁出现,可以在用户目录下的.wslconfig里给WSL2限制内存,避免Docker和Windows抢资源。

9. 特定场景与冷门问题:从KODBOX到国产环境

9.1 网盘类轻应用:KODBOX与DVWA的“一条命令”价值

docker部署kodbox是很常见的家庭或小团队需求。KODBOX是网盘应用,容器化部署在群晖或任意Linux服务器上都很方便,数据目录挂载出来就能用:

docker run -d \ --name kodbox \ -p 8080:80 \ -v /data/kodbox:/var/www/html \ kodbox/kodbox

注意数据卷要挂到宿主机足够大的磁盘上,网盘的容量是命根子。另外如果接了反向代理,记得把WebSocket相关配置带上,否则在线预览大文件会断连。

类似地,安全学习常用的DVWA靶场也能一条命令拉起:

docker run -d -p 8080:80 vulnerables/web-dvwa

这类实验环境用完即删,容器化“用完即走”的价值体现得淋漓尽致。

9.2 GitLab这种“重量级”选手:资源规划比命令更重要

GitLab的容器化部署也是一个高频搜索词。gitlab-ce镜像有好几个GB,内存建议至少4G,2G也能跑但明显卡顿。典型命令:

docker run -d \ --name gitlab \ -p 8022:22 -p 8080:80 \ --restart unless-stopped \ -v gitlab_config:/etc/gitlab \ -v gitlab_logs:/var/log/gitlab \ -v gitlab_data:/var/opt/gitlab \ gitlab/gitlab-ce:latest

部署后要修改/etc/gitlab/gitlab.rb里的external_url,改成实际访问的域名或IP,否则clone地址会不对。首次启动初始化很慢,docker logs -f gitlab里看到“gitlab Reconfigured!”才算完成,别以为卡住了。

9.3 人大金仓数据库与龙芯架构:兼容性要先确认

人大金仓数据库在政企场景用得不少,官方提供了Docker镜像,部署方式和其他关系型数据库类似,但特别要注意授权文件的位置,通常需要通过挂载方式提供给容器。容器化本身不复杂,复杂的是授权协议和厂商的部署要求。很多情况下不是技术不允许,而是许可证不覆盖容器场景,所以项目初期就要确认“是否允许容器化部署”这个前提。

热词里还有“龙芯 docker”。龙芯是LoongArch架构,和常见的x86_64、ARM64都不一样,很多镜像没有提供LoongArch版本,pull时会报not found manifest。解决办法通常是:

  1. 到镜像仓库搜是否有loongarch64标签的镜像。
  2. 官方没有就基于支持LoongArch的基础镜像自己构建。
  3. 很多开源社区已经有人在做龙芯适配,直接搜“镜像名 + loongarch”关键词。

跨架构问题的根本就是镜像和宿主机CPU架构必须匹配,理解了这一点,排查思路就清晰了。

9.4 定时任务类面板的依赖管理:用Dockerfile固化依赖

热词“docker青龙 依赖管理”反映了很多人在Docker里跑定时任务面板的困扰。这类面板本质是脚本执行器,容器里需要各种运行时依赖。常见的错误做法是图方便直接在容器里装:

docker exec -it qinglong bash -c "npm install -g xxx"

这样调试确实快,但容器一重建,依赖全没了。正确的做法是用Dockerfile构建自定义镜像,把依赖固化进去:

FROM whyour/qinglong:latest RUN npm install -g xxx && pip install xxx

构建成自己的镜像后再跑容器,无论容器怎么重建,依赖都在。我的观点一直很明确:凡是需要容器环境提供的东西,全部用Dockerfile固化,这才叫可复现的部署。

最后分享几点我自己沉淀下来的经验

第一,数据卷的命名规范要提前定好。我见过很多团队的volume名字乱七八糟,MySQL的数据叫data,Redis的也叫data,时间一长根本分不清哪个卷对应哪个服务。建议统一用项目名_服务名_data的格式。

第二,每一条docker run命令最好留档。如果你习惯用命令启动容器,就把命令保存成shell脚本,或者写成compose文件,别只躺在终端历史里。不然半年以后想查某台机器的MySQL当初是用什么参数启动的,根本无从下手。

第三,容器起不来、日志为空、排查无从下手时,按这个顺序走:先docker logs看输出,再docker inspect看状态,最后检查挂载目录的权限。绝大多数启动失败都出在这三件事上,别一上来就删容器重建,那样永远学不到根因。

这次先分享到这儿。Docker的内容远不止这些,镜像安全扫描、CI/CD集成、Kubernetes编排都还有大量可挖的东西。后面我会把微服务编排和灰度发布的实战经验陆续整理出来,感兴趣的话可以留意后续更新。遇到具体问题,也欢迎在评论区把你的docker run命令或完整报错贴出来,我们一起看看问题到底出在哪。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询