ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

从零搭建Docker开发环境:MySQL、Redis、Nginx与Compose实战

从零搭建Docker开发环境:MySQL、Redis、Nginx与Compose实战 这一两年不管是在技术社区还是公司内部聊到开发环境搭建几乎绕不开一个词——Docker。我自己从最早在笔记本上装一堆服务、搞坏系统重装到后来用Docker统一本地和服务器环境整个开发体验的差距真的不是一星半点。今天这篇博文我就用一套实际能落地的方案带你从零开始用Docker把一个完整的开发环境搭起来包括MySQL、Redis、Nginx、应用容器以及多站点域名配置这些常见需求。如果你是刚开始接触容器技术或者已经被环境依赖、版本冲突折磨过几次这篇文章应该能帮你少走不少弯路。先交代一下我这篇文章的适用范围以Windows环境为主同时兼顾macOS和Linux的差异点以开发环境为目标不涉及生产级的Kubernetes编排。我会从最基础的Docker安装讲起一直讲到用docker compose管理一套多服务开发环境再把最常见的坑虚拟化检测不过、网络不通、权限问题挨个拉出来聊。全程使用可复制的命令和配置你跟着操作就能跑通跑通过后再看原理理解会更快。1. 想清楚再动手这个开发环境到底要解决什么问题先说点反直觉的。很多人在学习Docker之前最大的误区是把它当成一个性能更好的虚拟机纠结“容器里跑数据库会不会比本机慢”。这种对比其实不是核心矛盾。Docker对开发者的价值更多体现在两个字一致。本地能跑同事拉下来也能跑不会因为操作系统不同、依赖版本不同就莫名其妙炸掉。这比那百分之几的性能损耗重要得多。1.1 为什么要用Docker而不是直接在宿主机装环境我见过很多同学的习惯是装个MySQL直接下载安装包装个Redis直接编译源码再装个Nginx还得处理系统自带的Apache冲突。最初几次确实能搞定但问题在下一次换电脑、或者项目需要升级某个组件版本的时候集中爆发——系统里残留的旧配置、端口占用、服务间依赖排查起来非常痛苦。Docker的思路从根本上改变了这件事。它把每个软件和它运行所需的完整环境代码、运行时、系统工具、库、配置文件打包成一个镜像。启动镜像就是启动一个隔离的容器容器里面爱怎么折腾都行不影响宿主机。你不需要在系统里装一大堆依赖库不需要处理端口冲突不需要担心卸载不干净。环境出了问题删掉容器重新拉一个就是。另外还有一点很实际团队协作。以前新人入职配环境光装MySQL和Redis可能就要折腾一天。现在只要装好Docker一个docker compose up -d就把整套环境拉起来了。这对开发团队的效率和一致性帮助非常大也是我强烈建议所有人都把Docker用起来的原因。1.2 用镜像版本锁住依赖告别“在我机器上能跑”后端开发最头疼的一句话就是“在我机器上能跑啊”。很多情况下问题就出在环境不一致本地MySQL是5.7测试库是8.0本地Redis没设密码部署机要求设密码本地PHP版本和线上差一个大版本。这些差异用传统方式很难管理因为你没法控制每台机器上的安装状态。Docker镜像通过tag锁版本把这个问题一次性解决。比如MySQL镜像指定mysql:8.0Redis指定redis:7.2-alpine那么不管在哪台机器上运行容器里的软件版本都是一样的。再加上通过Dockerfile定义应用自身的依赖整个环境就变成了代码的一部分。这是环境治理的一个根本性改变——环境不在是某台机器上的状态而是可版本化、可复现的产物。1.3 磁盘占用和性能真实感受分享关于性能我说一下我的实际体感。在Windows上用Docker Desktop运行MySQL、Redis这些开发用服务日常读写压力下基本感觉不到和本机安装的差别。容器多了一层虚拟化但这层开销在开发场景下完全可接受。唯一要注意的是文件挂载的性能在macOS和Windows上容器内读写挂载的宿主机目录比读写容器内部文件系统慢一些。典型做法是不要大量实时读写挂载目录高频数据用容器卷或数据库本身存储。磁盘占用这一块Docker确实比普通安装包大一些因为每个镜像都是多层文件系统的组合而且Docker Desktop自身的虚拟机文件也不算小。但镜像是可以复用的——多个容器共用同一个基础镜像层不会重复占用空间。日常注意清理悬空镜像和停止的容器后面我会给到具体的维护命令。2. 先把地基打好安装Docker并跑通第一个hello world环境搭建的第一步是把Docker本身装好。这个阶段最常见的报错是Windows上的Docker Desktop failed to start because virtualisation support wasnt detected很多人卡在这一步就放弃了。别急这个问题有标准的排查路径我拆开来讲。2.1 Windows下的安装步骤与前置条件Docker Desktop是Windows和macOS用户最常用的图形化客户端集成了引擎、命令行工具、镜像管理、容器管理等功能。Windows下安装它需要两个前置条件64位Windows 10/11以及CPU虚拟化功能开启。安装步骤并不复杂到Docker官网下载Docker Desktop安装包对应Windows版或Mac版。双击安装按提示走完流程。安装过程中会要求启用WSL 2或Hyper-V这一步选择WSL 2即可后面细说。安装完成后重启启动Docker Desktop等待右下角鲸鱼图标变为稳定状态。打开终端运行docker version看到Client和Server版本信息就说明安装成功。Linux用户则是另一种玩法用包管理器安装docker.io或docker-ce把当前用户加入docker组然后启动服务。命令如下sudo apt update sudo apt install docker.io sudo systemctl enable docker sudo systemctl start docker sudo usermod -aG docker $USER注意Linux下执行usermod后需要重新登录才生效否则每次执行docker命令都要加sudo。2.2 WSL 2和Hyper-V的区别怎么选很多Windows用户在安装Docker Desktop时会遇到一个选择用WSL 2还是Hyper-V作为后端。我的建议是优先WSL 2。WSL 2是微软推出的Windows子系统Linux第二版它和Hyper-V最大的区别在于启动速度和资源占用。WSL 2通过轻量级虚拟机技术实现真正的Linux内核比Hyper-V更轻更灵活启动一个发行版只需要几秒钟。Docker Desktop在此基础上运行体验很顺滑。需要额外说明的是WSL 2和VMware、VirtualBox这类传统虚拟机软件有潜在的冲突——因为它们都依赖Windows的虚拟化平台。如果你电脑上装了VMware并且开启Docker后出现蓝屏或无法启动多半是这个原因。解决办法是升级VMware到支持WSL 2的版本或者把WSL 2的内核和虚拟化平台设置理顺。2.3 报错排查虚拟化支持未检测到的完整处理流程这是Windows用户最常遇到的坎。报错信息一般是这样的Docker Desktop failed to start because virtualisation support wasnt detected.这行提示的意思是Docker Desktop检测不到CPU虚拟化能力。要解决它按顺序排查第一步检查BIOS设置。重启电脑进入BIOS不同品牌进入方式有差异常见的是开机按Delete或F2找到Intel Virtualization Technology或AMD SVM Mode确认状态为Enabled。如果之前没开过虚拟化这一步是关键。第二步检查Windows功能。在控制面板的“启用或关闭Windows功能”里确认Hyper-V、Windows虚拟机监控程序平台、适用于Linux的Windows子系统这三项是开启的。第三步确认WSL已安装且内核版本够新。打开PowerShell执行wsl --status查看版本信息。如果显示版本过旧运行wsl --update更新内核。第四步执行wsl --version确认输出正常。不少用户做完以上几步重启一次Docker Desktop就能正常启动了。排查的核心逻辑是Docker Desktop在Windows上的运行依赖虚拟化层虚拟化层又受BIOS开关和Windows功能开关双重控制。两者都正常Docker才能正常工作。2.4 拉镜像加速的配置方法安装好Docker之后第一件事不是急着跑环境而是配置镜像加速器。原因很现实Docker Hub在国内网络环境下的访问速度很不稳定拉个几百MB的镜像可能要等半天。配置方法很简单。打开Docker Desktop依次进入Settings - Docker Engine在配置文件的registry-mirrors字段里加入加速地址比如阿里云、网易等提供的公共加速地址保存后重启Docker Desktop。效果立竿见影原本要等十几分钟的大镜像几分钟就能拉完。注意加速器只对Docker Hub的镜像有效第三方仓库的镜像要单独配置登录凭证。配置好后验证一下docker info输出里能看到Registry Mirrors列表说明配置已生效。3. 第一次跑容器用MySQL实战掌握五个核心概念环境就绪后第一次真正跑容器我强烈建议从MySQL开始。原因很简单MySQL涉及镜像、tag、端口映射、数据卷、环境变量、初始化脚本等几乎所有核心概念跑通一个MySQL你对Docker的理解就上了一个台阶。这里有一个小前提你要对MySQL本身有一定基本了解知道它是干什么的。如果你连MySQL都没碰过也没关系跟着操作就行重点是理解Docker的概念。3.1 镜像和tag同样叫mysql差别可能很大在Docker世界里镜像相当于软件的安装包tag相当于版本号。你运行docker pull mysql时默认拉取的是mysql:latest标签的镜像也就是最新版。最新版往往不是最稳妥的选择——它可能包含新特性也可能有不兼容的变化。我个人的建议是除非有特殊需求否则生产研发环境都不要用latest而是明确指定版本tag。比如MySQL就用mysql:8.0或者mysql:5.7。指定版本的镜像经过更多验证行为可预期。当团队里出现“我本地是好的怎么到服务端就不行”的情况时检查一下是不是双方镜像版本不一致常常能直接发现问题。查看本机已有镜像的命令是docker images拉取镜像的命令是docker pull。比如docker pull mysql:8.0拉取完成后镜像就存在本地了后面启动容器不需要再联网。3.2 端口映射理解-p 3306:3306到底做了什么容器是一个隔离环境它内部有自己的网络命名空间。你在宿主机上访问MySQL的默认端口3306默认是访问不到的因为你宿主机上根本没有进程监听3306。要让宿主机能访问容器里的服务就得做端口映射。-p 3306:3306这个参数的格式是宿主机端口:容器端口。冒号左边是宿主机端口右边是容器内应用监听的端口。运行容器时Docker会建立一条转发规则所有发到宿主机3306端口的流量都转发到容器的3306端口。实际中你可能会遇到端口被占用的情况。比如本地已经有一个MySQL在跑占了3306。这时候可以改成-p 33306:3306这样你连接到宿主机的33306端口就相当于连接到了容器内的3306。这个灵活度是传统安装方式很难给到的——多开几个互相隔离的MySQL实例都没有问题。3.3 数据卷容器可以删数据不能丢容器本身是随时可以删除重建的但数据不行。如果直接把数据存在容器内部文件系统一旦容器被删除数据就彻底丢了。解决这个问题的方法是数据卷。数据卷有两种用法。最常用的是-v参数挂载目录把宿主机的某个目录挂载到容器内。比如-v /my/own/datadir:/var/lib/mysql意思是把宿主机的/my/own/datadir目录映射成容器内的/var/lib/mysql。MySQL写的所有数据都会落入宿主机这个目录。以后你删掉容器、重新拉镜像、再启动一个新容器只要还是挂载这个目录数据就原封不动还在。还有一种叫具名卷用法是-v mysql-data:/var/lib/mysql。这种方式的优点是卷由Docker管理不需要关心它在宿主机上的具体位置备份迁移也更方便。我第一次用Docker时犯过一个错误忘记挂载数据卷容器删了之后数据库里所有初始化数据全没了。从那以后我就形成了一个习惯凡是跑有状态的服务第一件事就是把数据目录挂载出来宁可多挂一个不用的目录也不要裸奔容器。3.4 环境变量用初始化配置代替手工建库建用户通过环境变量配置数据库实例是Docker镜像的一大便利。MySQL官方镜像支持一系列MYSQL_*环境变量常见的几个MYSQL_ROOT_PASSWORD指定root用户的密码MYSQL_DATABASE创建一个默认数据库MYSQL_USER和MYSQL_PASSWORD创建一个新用户和对应密码并赋予该用户对MYSQL_DATABASE的权限MYSQL_ALLOW_EMPTY_PASSWORD允许root空密码不建议生产环境使用用环境变量初始化实例比装好再手工建库建用户要方便得多。首次启动容器时镜像会自动处理初始化流程包括创建数据目录、初始化系统表、执行环境变量要求的内容。一个命令跑完带库带用户的MySQL就起来了。实际使用中我建议把环境变量和挂载目录配合使用环境变量解决初始化角色和权限挂载目录解决数据持久化二者结合最省心。3.5 时区与字符集国产项目绕不开的两个设置如果你开发过面向国内业务的项目一定知道数据库时区和字符集的重要性。很多人忽略这两点结果接出来的时间差8小时中文变成问号排查起来很崩溃。在Docker中这两个设置同样通过环境变量或者启动参数传入。MySQL镜像默认时区是UTC比北京时间慢8小时。解决方案是在启动容器时加上-e TZAsia/Shanghai字符集方面初始化时可以在/etc/mysql/conf.d下挂载一个自定义配置文件设置默认字符集为utf8mb4。有了这两个配置从源头避免了最让人头疼的编码和时间问题。3.6 完整启动一个MySQL观察整个过程把上面的知识点串起来一条完整的启动命令大概长这样docker run -d \ --name mysql-dev \ -p 3306:3306 \ -v mysql-data:/var/lib/mysql \ -v /my/own/mysql-config:/etc/mysql/conf.d \ -e MYSQL_ROOT_PASSWORDroot123456 \ -e MYSQL_DATABASEapp_db \ -e MYSQL_USERapp_user \ -e MYSQL_PASSWORDapp_pass \ -e TZAsia/Shanghai \ mysql:8.0逐项解释一下-d后台运行不占用当前终端--name mysql-dev给容器起个名字后面用这个名字查看日志、进入容器、停止删除都方便-p 3306:3306端口映射-v mysql-data:/var/lib/mysql数据持久化-v /my/own/mysql-config:/etc/mysql/conf.d挂载自定义配置后面几个-e环境变量mysql:8.0指定镜像和版本tag启动后先用docker ps确认容器状态再用docker logs mysql-dev观察启动日志。看到“ready for connections”字样说明已经初始化完成。然后用你熟悉的MySQL客户端连一下localhost:3306输入root密码看看能不能正常访问。4. 用docker compose管理多服务解锁一套完整开发环境跑通了单个MySQL接下来要面对更接近真实开发的需求一套环境里同时有MySQL、Redis、Nginx可能还有你的后端应用。手动一条条写docker run命令不仅繁琐还容易漏参数。这时候该轮到docker compose出场了。4.1 为什么需要docker compose一次启动全家桶到位docker compose的出现本质上是解决多容器编排的问题。它允许你用一个YAML文件描述整个应用栈包含哪些服务、每个服务的镜像、端口映射、数据卷、环境变量、依赖关系。一条docker compose up -d命令就能把整个环境拉起来docker compose down又能一键清理。相比一条条执行docker runcompose的优势很明显配置是声明式的整个环境长什么样一目了然环境定义变成文件可以提交到代码仓库团队共享服务之间的依赖关系可以用depends_on控制启动顺序支持环境变量注入一套配置多环境复用我自己的习惯是只要涉及两个以上服务的开发环境一律上compose。哪怕是临时起一个MySQL加一个Redis写个compose文件也不亏将来要加服务只需在文件里加一段就行。4.2 编排一个全家桶Nginx MySQL Redis 你的应用下面我给一个实际可用的compose文件这套组合能覆盖大多数Web项目的开发需求。文件名叫docker-compose.yml放在项目的根目录。完整内容如下version: 3.8 services: mysql: image: mysql:8.0 container_name: dev-mysql restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: root123456 MYSQL_DATABASE: app_db MYSQL_USER: app_user MYSQL_PASSWORD: app_pass TZ: Asia/Shanghai ports: - 3306:3306 volumes: - mysql-data:/var/lib/mysql - ./docker/mysql/conf:/etc/mysql/conf.d healthcheck: test: [CMD, mysqladmin, ping, -h, localhost] interval: 10s timeout: 5s retries: 5 redis: image: redis:7.2-alpine container_name: dev-redis restart: unless-stopped command: redis-server --requirepass redis123456 --appendonly yes ports: - 6379:6379 volumes: - redis-data:/data nginx: image: nginx:1.25-alpine container_name: dev-nginx restart: unless-stopped ports: - 80:80 - 443:443 volumes: - ./www:/var/www/html - ./docker/nginx/conf.d:/etc/nginx/conf.d depends_on: - mysql - redis app: build: . container_name: dev-app restart: unless-stopped ports: - 8080:8080 volumes: - .:/app environment: DB_HOST: mysql DB_PORT: 3306 DB_NAME: app_db DB_USER: app_user DB_PASSWORD: app_pass REDIS_HOST: redis REDIS_PORT: 6379 depends_on: mysql: condition: service_healthy redis: condition: service_started volumes: mysql-data: redis-data:这个文件里有几个值得注意的设计点。第一个是volumes里的./www和./docker/nginx/conf.d它们是相对路径挂载的是宿主机当前目录下对应的子目录。这样做的目的是你改的本项目代码容器里立刻能看到你改的Nginx配置容器里也立刻生效非常适合开发阶段的热更新。第二个关键是app服务用了build: .而不是image意思是这个服务不从仓库拉镜像而是通过当前目录下的Dockerfile现场构建。这是应用容器的标准做法——真正属于你自己项目的服务应该用Dockerfile描述依赖和启动方式。具体Dockerfile怎么写后面单独讲。第三个是depends_on配合healthcheck的用法。MySQL是有启动过程的如果App比MySQL先启动去连数据库就会连接失败。healthcheck可以让我们在MySQL真正就绪后再启动App解决了容器的启动顺序问题。Nginx的depends_on只写了服务名原因是它作为静态入口启动顺序要求没那么严格。4.3 写App的Dockerfile关键是要做到快速迭代如果你的应用是一个Python后端比如FastAPIDockerfile可以参考这样写FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple COPY . . CMD [uvicorn, main:app, --host, 0.0.0.0, --port, 8080]这段Dockerfile的核心逻辑是先拷依赖清单装好依赖再把代码拷进镜像最后声明启动命令。注意顺序是有考究的——requirements.txt先单独拷是因为它不常变。Docker构建镜像会利用层缓存只要文件没变后续步骤就不会重新执行。如果你把代码COPY放在依赖安装之前那么每次改代码依赖都要重新装一遍开发效率会大打折扣。开发阶段还有一个优化点在compose里我用volumes把当前目录挂载到容器的/app覆盖掉镜像里COPY进去的代码。这样改代码不需要重新构建镜像容器里就是最新代码配合支持热重载的开发服务器比如uvicorn的--reload参数改完代码保存服务自动重启。4.4 多站点自定义域名配置Nginx反向代理实战本地开发经常遇到一个场景一个Docker环境里要跑多个站点比如site1.test、site2.test都对应不同的项目目录。这是Nginx反向代理的经典用法Docker配合起来很舒服。先在宿主机设置域名解析。Windows下修改C:\Windows\System32\drivers\etc\hosts文件macOS/Linux修改/etc/hosts加入如下内容127.0.0.1 site1.test 127.0.0.1 site2.test然后在./docker/nginx/conf.d目录下为每个站点创建一个配置文件。比如site1.confserver { listen 80; server_name site1.test; location / { proxy_pass http://app1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }site2.conf类似只是把server_name和proxy_pass换成对应的站点。改完配置后重启Nginx容器让配置生效docker compose restart nginx然后浏览器访问http://site1.test就能看到第一个站点的内容了。访问http://site2.test看到第二个站点。两个站点在同一台机器、同一个Docker环境里互相隔离互不影响。这里有个细节容易踩坑容器之间通信用的不是localhost而是服务名。在上面Nginx配置里proxy_pass http://app1:8080中的app1是另一个容器的服务名。Docker compose会在同一个网络内为每个服务提供DNS解析所以Nginx能通过服务名找到对应的容器IP。千万别写成http://localhost:8080在容器内部localhost指向的是Nginx容器自身会连接失败。4.5 启动与常用管理命令配置都准备好后一键拉起整个环境docker compose up -d查看所有服务状态docker compose ps查看某个服务的日志比如appdocker compose logs -f app执行容器内命令比如进入MySQL容器操作数据库docker exec -it dev-mysql mysql -uroot -p停止所有服务docker compose down注意docker compose down默认会连网络一起删除但数据卷里的数据不会丢除非你加-v参数。这是刻意的设计——容器可重生数据要保留。5. 把常踩的坑挨个铲平从网络到权限的排查链路Docker用起来一点坑不踩是不可能的。我把自己这些年遇到的高频问题集中整理一下给到排查思路和解决命令。这些问题在热搜词里也大量出现说明确实是共性问题。5.1 容器内访问网络不通从三张网卡说起Docker网络出问题是新手遇到最多的报错之一表现是容器能正常启动但容器内curl外网或访问另一个容器不通。要理解这个问题得先了解Docker的三类网络模式。bridge模式默认模式。容器通过虚拟网桥访问外部网络相当于NAT转发host模式容器直接使用宿主机的网络命名空间没有端口映射直接监听宿主机端口none模式容器没有网络连接一般用于特殊场景排查网络问题先看当前容器用的是什么网络docker inspect container_name | grep NetworkMode如果是bridge模式再看它是否加入了正确的自定义网络。在docker compose环境下所有服务会自动加入一个以项目名为前缀的网络一般不需要手动管理。如果你在compose之外手动docker run一个容器想让它访问compose里的服务就需要把这个容器加入到同一个网络docker network connect 网络名 容器名网络名可以通过docker network ls查看。另一个常见的网络问题是DNS解析不了外部域名。容器默认使用Docker守护进程配置的DNS如果宿主机的DNS设置比较特殊容器里的域名解析可能会失败。解决办法是在启动容器时指定DNSdocker run --dns 8.8.8.8 --dns 114.114.114.114 ...或者在compose里给服务配dns字段。实际排查时先用docker exec -it 容器名 ping 目标IP测试链路通不通再测试域名解析分步缩小范围。5.2 权限问题从Permission denied到root用户Docker容器内的用户和宿主机不是同一个概念但权限事故还挺常见的。最典型的是挂载目录权限问题。宿主机上你用普通用户创建了一个项目目录挂载到容器里后容器内的进程可能没有权限读写。因为Linux的文件权限按UID/GID判断容器内进程的UID和宿主机用户的UID不一致就会互相“不认账”。解决思路有几种。一种是在compose文件里指定用户services: app: user: 1000:1000把UID固定为主机用户的UID容器内进程就以该用户身份运行读写挂载目录就没有障碍了。另一种是用chmod放宽目录权限。开发环境下图省事可以直接chmod -R 777但我不太推荐养成这个习惯它掩盖了权限问题的本质。Docker守护进程本身的权限问题也值得说。Linux下普通用户直接运行docker ps可能会提示权限不够因为Docker的socket文件默认归root所有。按前面说的把当前用户加入docker组后重新登录即可。注意这个操作有一定风险——加入docker组的用户相当于获得了root级别能力在多用户机器上要谨慎。5.3 Windows下的文件挂载性能慢一个实用的优化策略在Windows上用Docker做开发文件挂载性能慢是一个绕不开的话题。尤其是在宿主机和容器之间大量读写小文件时比如前端构建、日志输出延迟会非常明显。原因是跨操作系统边界访问文件需要经过虚拟化层的转换开销比较大。针对这个问题我推荐一个实用的优化策略高频读写的目录不要走宿主机挂载而用具名卷。比如数据库数据目录、某个服务产生的临时文件目录都改成Docker管理的具名卷性能会好很多。代码目录这种低频高价值的挂载保留在宿主机兼顾可编辑性和性能。另外把项目的日志输出到容器内而不是直接写到挂载目录也是一种常见做法。如果你发现某台电脑上Docker环境特别卡优先检查文件挂载多半能找到突破口。5.4 一不小心磁盘就满了镜像和构建缓存的清理Docker让你免于系统环境污染的代价是把垃圾留给了自己。随着镜像越拉越多、构建缓存越积越厚磁盘占用会逐渐膨胀。下面几个命令是每个Docker用户都应该掌握的查看磁盘占用总览docker system df清理悬空镜像无标签且不再被使用的镜像层docker image prune清理停止的容器、无用网络、悬空镜像一步到位docker system prune -a --volumes注意最后这条比较激进-a会删除所有未被运行的镜像--volumes会删除未挂载使用的卷。用之前要确认没有需要保留的数据。我的习惯是日常用docker system prune -f只清悬空大扫除才用全量的。6. 我个人的使用习惯让Docker真正融入日常开发流程前面把环境搭建、多服务编排、问题排查都讲完了最后这部分不算教程算是个人经验总结。我把这段时间用下来比较顺手的工作流分享出来你可以参考着调整成自己的。6.1 关于环境一致性的坚持与妥协我给自己定了一个规矩主项目涉及的服务必须在compose文件里有定义不要图方便在宿主机直接装一份。这也是最彻底贯彻“环境即代码”的方式。哪怕是很简单的MySQL也把它写进compose。好处是团队其他人拿到项目后一条命令就能启动完整环境不需要自己看文档装服务。妥协的地方也有比如公司内部有统一的代码规范和工具链我不强行把它们搬进容器。开发流程的工具选择可以灵活但运行环境的一致性必须保证。6.2 环境备份与快速恢复的实践Docker让环境备份变成一件很轻松的事。数据在具名卷里配置在compose文件里镜像定义在Dockerfile里。备份数据卷用一条命令就能导出docker run --rm -v 卷名:/backup-source -v /宿主机路径:/backup-dest alpine tar czf /backup-dest/backup.tar.gz -C /backup-source .恢复导出也是一样把压缩包解压回卷里就行。换新电脑时只要代码仓库里有compose文件和Dockerfile重新执行docker compose up -d整个开发环境就原地复现了。这套流程真的很省心尤其是对比以前换电脑装环境动辄半天的经历。6.3 未来扩展思路从compose到集群的平滑过渡如果你的项目将来需要部署到服务器上这套以compose为核心的环境可以平滑过渡。原因在于compose文件可以继续用于单机生产部署而Docker Swarm或Kubernetes也提供了与compose类似的服务编排模型。把它们理解为一件事的不同抽象层次就好本地是简化版生产是完整版。在实际扩展中建议先关注动静分离静态资源走Nginx挂载目录动态服务走独立容器数据库和缓存这类有状态服务单独管理。把环境职责分清楚了后续加服务、改配置、迁机器都会从容很多。最后再分享一个很具体的小技巧开发调试时不要怕反复重建容器。容器是廉价的环境是代码化的大胆地改配置、删容器、重建。踩过几次坑之后你就会发现那句“在我机器上能跑啊”的烦恼在容器化的开发环境里会越来越少。
返回列表