
简介这份《Docker新手完全指南从入门到实战万字大全》面向零基础初学者与有一定经验的技术人员尤其适合对容器化技术感兴趣的开发者、运维人员和架构师。内容从容器与虚拟机的本质差异切入系统梳理镜像、容器、仓库三大核心概念并覆盖Linux、Windows、macOS跨平台安装配置及镜像加速避坑要点。资源包为1个PDF文件约1004KB篇幅精炼却信息密度高便于随时查阅。文档深入讲解容器生命周期管理、镜像管理与诊断调试命令通过多阶段构建等Dockerfile实践指导高效镜像编写并延伸至数据卷持久化、网络模式选择与Docker Compose多容器编排最后附常见问题排错指南与进阶学习路径。目前已有201人学习适合希望从零掌握容器化应用开发、测试与部署全流程的读者按章节循序渐进地实操演练。1. 从一台干净的 Linux 机器说起Docker 到底解决了谁的痛刚拿到一台全新的 Ubuntu 服务器或者本地刚装好 Windows 想跑个 Redis 练手第一反应往往是「我该装什么、装哪个版本、装完怎么不冲突」。传统做法是 apt 装一遍、pip 装一遍、手动改配置文件、再 export 一堆环境变量换台机器重来一遍版本对不上就翻车。Docker 把「应用 依赖 配置」打包成一个镜像容器启动时按镜像还原环境一致性问题基本被抹平。这篇指南面向的是刚接触容器、想在自己机器上把 Docker 跑起来并部署几个真实服务的人从安装、镜像、Dockerfile、Docker Compose 一路讲到资源隔离和排错。读完你应该能独立写出一个能用的 Dockerfile用 Compose 拉起 MySQL、Redis、Nacos 这类常见服务并且知道容器网络不通、权限报错时该往哪查。2. 安装 Docker 与 Docker Desktop三条路径怎么选2.1 Linux 上用官方脚本装 Docker EngineLinux 服务器是最常见的落地场景Ubuntu、CentOS 7、UOS 这类系统都适用。官方提供了一键脚本但生产环境我更建议走 apt 仓库方便后续升级和锁版本。# 卸载可能存在的旧版本避免依赖冲突 sudo apt-get remove docker docker-engine docker.io containerd runc # 安装基础依赖ca 证书、curl、gnupg sudo apt-get update sudo apt-get install -y ca-certificates curl gnupg # 添加 Docker 官方 GPG key用于校验包来源 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 ar /etc/apt/keyrings/docker.gpg # 写入 apt 源注意 $(lsb_release -cs) 会取当前发行版代号 echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] \ https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | \ sudo tee /etc/apt/sources.list.d/docker.list /dev/null # 安装 engine、cli、containerd 和 compose 插件 sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin # 把当前用户加入 docker 组避免每条命令都 sudo sudo usermod -aG docker $USER逻辑上分四步清旧、加源、装包、配权限。docker-compose-plugin装完后命令是docker compose中间空格不是老的docker-compose。如果你敲docker compose报unknown command八成是只装了老的独立二进制或者插件没装上用docker compose version验证一下。加入 docker 组后要重新登录 shell 才生效否则还是得 sudo。CentOS 7 的步骤类似把 apt 换成 yum源地址换成https://download.docker.com/linux/centos/docker-ce.repo。CentOS 7 已停止维护很多镜像源同步慢建议提前配好可用的镜像加速地址否则docker pull会卡到怀疑人生。2.2 Windows 上装 Docker Desktop 与 WSL2 前置条件Windows 用户最省事的是 Docker Desktop但它对系统有硬性要求Win10 2004 以上或 Win11开启 WSL2 或 Hyper-V。装完启动如果报Virtualization support not detected说明 BIOS 里虚拟化没开或者 Hyper-V/WSL2 没启用。先在「启用或关闭 Windows 功能」里勾上「虚拟机平台」和「适用于 Linux 的 Windows 子系统」再wsl --update更新内核。Docker Desktop 装好后Settings 里可以调 CPU、内存、磁盘镜像位置。默认镜像放在 C 盘跑几个大镜像 C 盘就红了建议在 Resources 里把 Disk image location 改到其他盘。Windows 下挂载目录要注意路径写法-v D:\data:/data这种反斜杠在部分终端会被转义稳妥写法是-v /d/data:/data或者用双反斜杠。2.3 国内网络下配置镜像加速不管哪个平台拉镜像慢是常态。配置镜像加速的入口在/etc/docker/daemon.jsonLinux或 Docker Desktop 的 Docker Engine 设置里。{ registry-mirrors: [ https://docker.m.daocloud.io, https://dockerproxy.com ], log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 } }registry-mirrors是镜像加速地址列表按顺序尝试。log-opts限制单个容器日志大小不加这个跑久了的容器日志能把磁盘写满这是血泪经验。改完执行sudo systemctl daemon-reload sudo systemctl restart docker生效。注意镜像加速地址会失效用之前先确认当前可用性别照抄一个几年前的地址。3. 镜像与容器把「一次构建到处运行」落到命令上3.1 镜像分层与常用拉取、查看命令镜像不是一整块文件而是若干只读层叠加最上面加一个可写层就是容器。这个设计让相同基础层的镜像共享磁盘也解释了为什么docker pull有时只下几 MB——公共层本地已经有了。# 拉取指定版本别用 latest版本不可控 docker pull redis:7.2-alpine # 查看本地镜像含镜像 ID、大小、创建时间 docker images # 查看镜像分层历史排查为什么镜像这么大 docker history redis:7.2-alpine # 查看镜像详细信息含环境变量、入口命令 docker inspect redis:7.2-alpinedocker images里的 IMAGE ID 是短 IDdocker inspect用短 ID 或完整 ID 都行。docker history能看出每层多大如果某层异常大通常是 COPY 了一个大文件或者 apt 缓存没清。选基础镜像时alpine体积小但用的是 musl libc某些依赖 glibc 的二进制跑不起来slim是 Debian 精简版兼容性好一些体积居中。生产上我一般优先slim除非对体积极度敏感。3.2 启动、进入、清理容器的完整命令链# 后台启动一个 Redis映射端口并挂载数据目录 docker run -d --name my-redis \ -p 6379:6379 \ -v /data/redis:/data \ --restart unless-stopped \ redis:7.2-alpine redis-server --appendonly yes # 进入运行中的容器调试用 docker exec -it my-redis sh # 查看容器日志-f 持续输出 docker logs -f --tail 100 my-redis # 停止并删除容器-v 同时删匿名卷 docker rm -f my-redis # 清理无用镜像、容器、网络、构建缓存 docker system prune -a-d后台运行--name指定名字方便后续操作-p 6379:6379是「宿主端口:容器端口」-v挂载目录保证数据不随容器删除而丢失--restart unless-stopped让容器随 Docker 启动自动拉起。docker exec进去后如果容器里没有 bash用sh。docker system prune -a会删掉所有没在用的镜像执行前想清楚别把正在用的基础镜像删了。提示-v挂载的宿主目录如果不存在Docker 会自动创建但属主是 root。容器内非 root 用户写不进去时先chown宿主目录或者用--user指定 UID。3.3 容器网络模式与端口映射的取舍默认的 bridge 网络下容器之间要通过 IP 通信IP 会变不靠谱。自定义 bridge 网络支持用容器名当主机名解析这是 Compose 能工作的基础。# 创建自定义网络 docker network create my-net # 两个容器加入同一网络可直接用名字互访 docker run -d --name app --network my-net my-app docker run -d --name db --network my-net mysql:8.0 # 此时 app 容器内 ping db 能通host模式让容器直接用宿主网络栈性能好但端口会冲突且失去隔离。none模式只有 loopback适合纯计算任务。排查「docker 网络不通」时先docker network inspect my-net看容器是否真的加入了同一网络再进容器ping对方名字最后查宿主防火墙。很多时候不是 Docker 的问题是宿主 iptables 或安全组拦了。4. 写一个能上生产的 Dockerfile从能跑到跑得好4.1 多阶段构建把镜像从 1G 压到 100M以 Java 应用为例如果直接在构建镜像里编译再运行镜像里会带上 Maven、JDK 全套动辄 800M 起步。多阶段构建把编译和运行分开运行阶段只留 JRE 和 jar 包。# 阶段一构建用带 Maven 的镜像 FROM maven:3.9-eclipse-temurin-17 AS builder WORKDIR /build # 先拷 pom利用层缓存依赖没变就不重新下载 COPY pom.xml . RUN mvn dependency:go-offline -B COPY src ./src RUN mvn clean package -DskipTests # 阶段二运行只留 JRE FROM eclipse-temurin:17-jre-jammy WORKDIR /app # 从构建阶段拷贝产物 COPY --frombuilder /build/target/*.jar app.jar # 用非 root 用户运行降低权限风险 RUN useradd -r -u 1001 appuser USER appuser EXPOSE 8080 ENTRYPOINT [java, -jar, app.jar]关键点有三个COPY pom.xml单独一层让依赖下载结果被缓存改代码不会触发重新下依赖COPY --frombuilder只搬产物不搬构建工具USER appuser切非 root。最后一条经常被忽略容器默认 root 运行一旦被突破就是宿主 root 权限这是镜像安全和容器安全里最基础的一条。4.2 层缓存、.dockerignore 与构建参数.dockerignore的作用和.gitignore一样但很多人不写结果COPY . .把node_modules、.git、日志全打进镜像构建慢、镜像大。# .dockerignore .git node_modules target *.log .env .idea构建参数用ARG声明--build-arg传入适合区分环境的配置。但注意ARG的值会留在镜像历史里密码这类敏感信息别用 ARG用运行时环境变量或 secret 挂载。# 构建并打标签标签带版本号 docker build -t my-app:1.0.0 --build-arg PROFILEprod . # 查看构建缓存命中情况CACHED 说明复用了层 docker build -t my-app:1.0.1 .层缓存的规则是某层变了它之后的所有层都失效。所以 Dockerfile 里把变化频率低的放前面变化频率高的放后面。RUN apt-get install后面记得跟 rm -rf /var/lib/apt/lists/*否则 apt 缓存会留在层里白白多几十 MB。4.3 镜像瘦身与安全扫描的实操瘦身三板斧换小基础镜像、多阶段构建、清理临时文件。安全扫描可以用docker scout或trivy扫出基础镜像里的已知漏洞。# 用 trivy 扫描镜像漏洞 trivy image my-app:1.0.0 # 只看高危和严重 trivy image --severity HIGH,CRITICAL my-app:1.0.0扫描结果里基础镜像的漏洞占大头所以选一个维护活跃的基础镜像比事后修补更重要。alpine漏洞少但兼容性差debian:slim折中。扫描不是一次性的基础镜像更新后要重新构建重新扫。别把扫描当形式真出问题时它就是那个后悔药。5. Docker Compose 编排一条命令拉起 MySQL、Redis 和 Nacos5.1 compose 文件结构与 depends_on 的真实语义Compose 用一个 YAML 描述多个服务docker compose up -d一键拉起。下面是一个 MySQL 8.0 Redis 主从 Nacos 3.x 的典型组合。services: mysql: image: mysql:8.0 container_name: mysql8 environment: MYSQL_ROOT_PASSWORD: root_pwd MYSQL_DATABASE: nacos ports: - 3306:3306 volumes: - ./mysql/data:/var/lib/mysql - ./mysql/conf:/etc/mysql/conf.d command: --character-set-serverutf8mb4 --collation-serverutf8mb4_unicode_ci healthcheck: test: [CMD, mysqladmin, ping, -h, localhost] interval: 10s retries: 5 redis-master: image: redis:7.2-alpine container_name: redis-master ports: - 6379:6379 command: redis-server --appendonly yes redis-slave: image: redis:7.2-alpine container_name: redis-slave command: redis-server --replicaof redis-master 6379 depends_on: - redis-master nacos: image: nacos/nacos-server:v3.0.0 container_name: nacos environment: MODE: standalone SPRING_DATASOURCE_PLATFORM: mysql MYSQL_SERVICE_HOST: mysql MYSQL_SERVICE_DB_NAME: nacos MYSQL_SERVICE_USER: root MYSQL_SERVICE_PASSWORD: root_pwd ports: - 8848:8848 - 9848:9848 depends_on: mysql: condition: service_healthydepends_on默认只保证启动顺序不保证依赖服务「就绪」。MySQL 容器起来了但还没初始化完Nacos 连上去照样报错。所以 MySQL 配了healthcheckNacos 用condition: service_healthy等健康检查通过再启动。这是 Compose 里最容易踩的坑之一。5.2 环境变量、卷与网络在 Compose 里的写法环境变量可以写在environment里也可以放.env文件让 Compose 自动读取。密码这类别硬编码在 YAML 里提交到仓库用.env并加进.gitignore。# .env 文件 MYSQL_ROOT_PASSWORDroot_pwd NACOS_VERSIONv3.0.0# compose 里引用 environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} image: nacos/nacos-server:${NACOS_VERSION}卷分两种./mysql/data:/var/lib/mysql是绑定挂载数据落在项目目录方便备份mysql-data:/var/lib/mysql是命名卷由 Docker 管理跨项目复用。绑定挂载要注意宿主目录权限MySQL 容器内是 mysql 用户宿主目录属主不对会启动失败日志里报Permission denied。Compose 默认给项目创建一个网络所有服务自动加入服务名就是主机名。所以 Nacos 里写MYSQL_SERVICE_HOST: mysql就能连上不用写 IP。跨项目通信才需要显式声明 external 网络。5.3 常用 Compose 命令与滚动更新# 后台启动全部服务 docker compose up -d # 只看某个服务日志 docker compose logs -f nacos # 重新构建并重启某个服务改代码后用 docker compose up -d --build nacos # 停止并删除容器、网络保留卷 docker compose down # 连卷一起删数据没了慎用 docker compose down -v # 查看服务状态和健康检查结果 docker compose psdocker compose ps会显示健康状态healthy才算真正就绪。滚动更新时Compose 默认先停旧再起新有短暂中断要零中断得配合deploy.replicas和反向代理那是 Swarm 或 K8s 的范畴了。单机场景下up -d --build够用。注意docker compose和docker-compose是两个东西。前者是插件后者是老的 Python 独立版。命令报unknown command: docker compose说明插件没装装docker-compose-plugin即可。6. 避坑与排查容器跑不起来时先看这几处6.1 容器启动即退出日志只有一行现象docker run -d后docker ps看不到容器docker ps -a显示Exited (1)。原因通常是主进程前台运行失败比如命令写错、配置文件缺失、端口被占。解决docker logs 容器名看退出前的输出再docker run -it 镜像 sh手动进去跑一遍命令定位是哪一步挂的。容器的主进程必须前台运行如果 Dockerfile 里 CMD 跑的是后台脚本进程一退容器就退。6.2 挂载目录权限报 Permission denied现象MySQL、Nginx 这类容器挂载宿主目录后启动失败日志报无法写入。原因是容器内进程以非 root 用户运行而宿主目录属主是 root。解决chown -R 1001:1001 ./data把宿主目录属主改成容器内用户 UID或者在 compose 里加user: 1001:1001。别图省事直接chmod 777那是把权限问题变成安全问题。6.3 容器间网络不通ping 名字失败现象两个容器在同一 Compose 项目里A 连不上 B。原因可能是没在同一网络、服务名写错、或者 B 还没就绪。解决docker network inspect 网络名确认两个容器都在进 A 容器getent hosts B看能否解析如果解析正常但连不上查 B 的端口是否监听在 0.0.0.0 而不是 127.0.0.1。很多应用默认只监听 localhost容器外自然连不上改配置监听0.0.0.0。6.4 磁盘被日志和镜像撑满现象docker ps正常但宿主磁盘 100%服务陆续挂掉。原因容器日志没限制大小或者docker system prune长期没跑悬空镜像堆积。解决daemon.json 里配log-opts限制单容器日志大小定期docker system df看占用docker image prune清悬空镜像。生产上建议把 Docker 数据目录迁到独立大盘别和系统盘混用。6.5 Windows 下挂载目录路径与换行符问题现象Windows 上-v D:\code:/app挂载后容器里文件为空或路径报错。原因路径分隔符和盘符写法在 Git Bash、PowerShell、CMD 里不一致。解决统一用/d/code:/app这种形式或者在 Docker Desktop 的 File Sharing 里确认该盘已授权。另外 Windows 的 CRLF 换行符会让 shell 脚本在 Linux 容器里报\r: command not found用dos2unix转一下或者编辑器设成 LF。7. 把容器资源管起来CPU、内存限制与运行时调优容器默认不限制资源一个跑飞的 Java 进程能把宿主内存吃光拖垮其他服务。限制资源在docker run或 compose 里都能配。# 限制 CPU 为 1.5 核内存 1G内存swap 1.5G docker run -d --name app \ --cpus1.5 \ --memory1g \ --memory-swap1.5g \ my-app:1.0.0--cpus是软限制按比例分配--memory是硬限制超了容器内进程会被 OOM Killer 干掉。--memory-swap要大于等于--memory等于时表示禁用 swap。Java 应用尤其要注意JVM 默认按宿主内存算堆大小容器里不设-Xmx会按宿主内存分配一启动就被 OOM。JDK 10 以后支持-XX:MaxRAMPercentage按容器内存比例设堆比写死-Xmx更灵活。# 容器内 JVM 按容器内存的 75% 设堆 java -XX:MaxRAMPercentage75.0 -jar app.jar验证限制是否生效用docker stats实时看 CPU、内存、网络 IO。如果内存一直贴着上限说明限制太紧或者有内存泄漏先调大再排查。CPU 限制下如果docker stats显示 CPU 长期 100%说明该加核或者优化代码了。进阶一点可以用--cpuset-cpus把容器绑到特定核减少上下文切换适合对延迟敏感的服务。--blkio-weight调磁盘 IO 权重多容器争抢磁盘时有用。这些参数不是越多越好先跑起来观察docker stats有瓶颈再针对性调。我自己习惯是每个生产容器都设内存上限哪怕设得宽松也比不设强——不设的话一个内存泄漏就能让整台机器失联那种半夜被叫起来重启服务器的经历一次就够了。希望帮到你。本文还有配套的精品资源点击获取