简介:这份PDF面向零基础或缺乏容器化经验的开发者与运维人员,系统梳理Docker从概念到实战的完整入门路径。内容涵盖容器与虚拟机的差异对比、Ubuntu环境下的安装与用户组配置、镜像与容器生命周期管理、调试日志技巧,并以部署WordPress为例演示docker-compose.yml编写与服务启动,同时讲解数据卷与绑定挂载两种持久化方案及容器安全最佳实践。资源包共1个PDF文件,大小约760KB,篇幅紧凑、结构清晰,适合作为案头速查手册。目前已有1057人学习,说明其内容经过一定规模读者验证。读者可借此快速搭建本地Docker环境,掌握常用命令与排错思路,并通过WordPress实战理解多容器编排流程,为后续进阶学习打下基础。
1. 从一台干净的 Ubuntu 说起:这份 Docker 入门指南到底能帮你省掉哪些弯路
如果你手上有一台刚装好的 Ubuntu,想跑个 Nginx 或者 WordPress,传统做法是apt install一堆依赖,然后开始跟版本冲突、端口占用、配置文件路径搏斗。这份《Docker 新手入门指南:从零开始掌握容器化技术》解决的正是这个场景——它不讲空泛的容器哲学,而是从卸载旧版本、配软件源、装 Docker Engine 一路写到用 docker-compose 起一套 WordPress,中间穿插镜像管理、容器生命周期、数据卷和绑定挂载。适合两类人:一是刚接触容器化技术、需要一份能照着敲的实操手册的开发者;二是运维转云原生、想把 Docker 安装教程和 docker-compose 编排一次性跑通的从业者。它不覆盖 Kubernetes,也不深入网络模式,但把单机容器化最常用的 80% 操作讲透了。
2. 安装与权限配置:Ubuntu 上把 Docker Engine 装干净
2.1 为什么不用 apt 自带的 docker.io
Ubuntu 官方源里的docker.io版本通常落后于 Docker 官方仓库,而且包名和依赖关系跟官方docker-ce不一致。常见做法是先把旧版本清掉,再通过 Docker 官方 GPG key 和软件源安装。这份指南给的就是官方仓库路线,好处是后续docker compose插件、docker buildx都能一起装上,不用单独折腾。另一个容易被忽略的点是containerd和runc的版本——官方源会一并管理,避免手动装出现版本错配。
2.2 安装命令逐段拆解
# 卸载可能存在的旧版本,避免包冲突 sudo apt-get remove docker docker-engine docker.io containerd runc # 更新索引并安装证书、curl、gnupg sudo apt-get update sudo apt-get install ca-certificates curl gnupg # 创建 keyrings 目录,权限 0755 sudo install -m 0755 -d /etc/apt/keyrings # 下载 Docker 官方 GPG key 并解码存放 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 # 写入软件源,arch 和 VERSION_CODENAME 自动取当前系统值 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 # 安装 Docker Engine、CLI、containerd 以及 buildx、compose 插件 sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io \ docker-buildx-plugin docker-compose-plugin # 验证:拉取 hello-world 并运行 sudo docker run hello-world逻辑说明:install -m 0755 -d确保 keyrings 目录存在且权限正确,否则gpg --dearmor会因目录不存在报错。$(dpkg --print-architecture)和$(. /etc/os-release && echo "$VERSION_CODENAME")是让软件源自动适配当前架构和 Ubuntu 代号,避免手写jammy或focal写错。最后一步docker run hello-world不只是验证安装,它还会检查 Docker daemon 是否在运行、能否拉取镜像、容器能否正常启动——三个环节一次过。
参数说明:docker-ce是社区版引擎,docker-ce-cli是命令行客户端,containerd.io是底层容器运行时,docker-buildx-plugin提供多平台构建能力,docker-compose-plugin让你能用docker compose而不是老式的docker-compose二进制。
2.3 把当前用户加入 docker 组
装完之后每次敲docker都要加sudo,原因是/var/run/docker.sock默认属于 root。把用户加入 docker 组就能免 sudo:
# 创建 docker 组(已存在会提示,忽略即可) sudo groupadd docker # 将当前用户加入 docker 组 sudo usermod -aG docker $USER # 刷新当前 shell 的组信息,或者直接退出重新登录 newgrp docker # 验证:不加 sudo 运行 hello-world docker run hello-world逻辑说明:usermod -aG的-a是追加,不加-a会把你从其他附加组里踢出去。newgrp docker只对当前终端生效,新开的终端会自动读取新组。如果newgrp后仍然提示权限拒绝,检查/var/run/docker.sock的属组是不是 docker,常见情况是 Docker 服务没重启导致 socket 属组没更新。
注意:把用户加入 docker 组等同于给了该用户 root 级权限,因为容器可以挂载宿主机根目录。生产环境里更稳妥的做法是用 rootless 模式或 sudo 白名单,但开发机上加组是常规操作。
3. 镜像与容器生命周期:把 docker run 的参数吃透
3.1 镜像管理:pull、images、rmi、build
镜像操作是日常最高频的动作。这份指南列了四条命令,但实际用起来有几个细节值得展开:
# 拉取 nginx 最新版镜像 docker pull nginx:latest # 查看本地镜像,含镜像 ID、标签、大小 docker images # 删除指定镜像 docker rmi nginx:latest # 根据当前目录的 Dockerfile 构建镜像,打标签 myapp:v1 docker build -t myapp:v1 .逻辑说明:docker pull nginx:latest里的latest是默认标签,但生产环境不建议用latest,因为每次拉取可能拿到不同版本,导致“昨天还能跑今天挂了”的玄学问题。docker images输出里的 IMAGE ID 是短 ID,删除时可以用短 ID 也可以用仓库:标签。docker rmi如果镜像被容器引用会报错,需要先删容器或加-f强制。docker build最后的.是构建上下文路径,不是 Dockerfile 路径——Dockerfile 默认在上下文根目录,用-f可以指定其他位置。
参数说明:-t给镜像打标签,格式是名称:版本;--no-cache在构建时禁用缓存,排查“改了代码但镜像没变”时用;--platform指定目标架构,比如在 x86 机器上构建 arm64 镜像。
3.2 容器生命周期:run、ps、stop、start、rm
容器生命周期命令看似简单,但docker run的参数组合是新手翻车最多的地方:
# 后台运行 nginx,把宿主机 80 映射到容器 80,命名 my-nginx docker run -d -p 80:80 --name my-nginx nginx # 查看运行中的容器 docker ps # 查看所有容器,包括已停止的 docker ps -a # 停止、启动、删除容器 docker stop my-nginx docker start my-nginx docker rm my-nginx逻辑说明:-d让容器在后台运行,不加的话终端会被前台进程占住。-p 80:80是宿主机端口:容器端口,顺序反了就连不上。--name给容器起名,不起名的话 Docker 会随机分配一个名字,后续操作得先docker ps查 ID。docker stop发送 SIGTERM 并等待 10 秒,超时再 SIGKILL;docker rm只能删已停止的容器,运行中的要加-f。
参数说明:-it组合用于交互式容器,-i保持 stdin 打开,-t分配伪终端;--restart控制重启策略,always是开机自启,unless-stopped是除非手动停止否则自启;-e注入环境变量,WordPress 案例里大量用到。
3.3 调试与日志:exec、logs、inspect
容器出问题时,这三个命令是主要排查手段:
# 进入容器终端,bash 不存在时换 sh docker exec -it my-nginx bash # 查看容器日志,-f 持续输出,--tail 只看最后 N 行 docker logs -f --tail 100 my-nginx # 查看容器详细信息,输出 JSON docker inspect my-nginx逻辑说明:docker exec是在运行中的容器里开一个新进程,容器停了就用不了,得用docker start先起来。docker logs读的是容器主进程的 stdout/stderr,如果应用把日志写到文件里,logs 看不到,得 exec 进去 cat。docker inspect输出很长,常用--format过滤,比如docker inspect --format='{{.NetworkSettings.IPAddress}}' my-nginx直接拿 IP。
参数说明:exec的-it和run一样;logs的--since按时间过滤,--timestamps加时间戳;inspect的-f或--format用 Go 模板语法提取字段。
提示:
docker exec进去之后做的修改不会保存到镜像,容器删除就没了。要持久化得改 Dockerfile 重新构建,或者用数据卷挂载。
4. 用 docker-compose 部署 WordPress:多容器编排的第一课
4.1 为什么 WordPress 适合当第一个 compose 项目
WordPress 需要两个服务:MySQL 数据库和 WordPress 本身。用docker run起两个容器再手动连网络、传环境变量也能跑,但 compose 用一个 YAML 文件就把依赖关系、网络、卷全声明了。这份指南给的 compose 文件是经典的最小可用配置,适合理解services、volumes、depends_on、environment四个核心字段。
4.2 docker-compose.yml 逐字段拆解
version: '3' services: db: image: mysql:8.0 volumes: - db_data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: rootpass MYSQL_DATABASE: wordpress MYSQL_USER: wpuser MYSQL_PASSWORD: wppass wordpress: image: wordpress:latest ports: - "8000:80" environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: wpuser WORDPRESS_DB_PASSWORD: wppass depends_on: - db volumes: db_data:逻辑说明:db服务用mysql:8.0镜像,volumes把命名卷db_data挂到/var/lib/mysql,这样容器删了数据还在。environment里的四个变量是 MySQL 镜像约定的初始化参数,MYSQL_DATABASE会自动建库,MYSQL_USER和MYSQL_PASSWORD会自动建用户并授权。wordpress服务把宿主机 8000 映射到容器 80,WORDPRESS_DB_HOST写db是因为 compose 默认给所有服务建一个网络,服务名就是 DNS 名。depends_on只保证启动顺序,不保证 MySQL 就绪——WordPress 启动时如果 MySQL 还没初始化完,会报连接失败,但刷新几次就好了。
参数说明:version: '3'是 compose 文件格式版本,新版 Docker 可以省略;ports的引号建议保留,避免 YAML 把8000:80解析成时间;volumes顶层声明命名卷,服务里引用时写卷名:容器路径。
4.3 启动、验证与常见调整
# 在 docker-compose.yml 所在目录执行,后台启动 docker compose up -d # 查看服务状态 docker compose ps # 查看某个服务的日志 docker compose logs -f wordpress # 停止并删除容器、网络,但保留卷 docker compose down # 停止并删除容器、网络、卷 docker compose down -v逻辑说明:docker compose up -d会按依赖顺序创建网络、卷、容器。docker compose ps显示的是 compose 项目下的容器,比docker ps更聚焦。docker compose down默认不删卷,数据还在;加-v才删卷,这个参数用之前想清楚,删了就找不回来。
访问http://localhost:8000就能看到 WordPress 安装界面。如果页面报“Error establishing a database connection”,先docker compose logs db看 MySQL 是否初始化完成,再docker compose logs wordpress看连接参数。常见原因是 MySQL 8.0 的认证插件和旧版 WordPress 不兼容,但wordpress:latest已经处理了这个问题。
注意:compose 文件里的密码是明文,本地开发无所谓,放到版本控制里之前记得改成环境变量文件
.env并加入.gitignore。
5. 数据持久化与安全:卷、绑定挂载和非 root 运行
5.1 数据卷与绑定挂载的选型
Docker 的数据持久化有两种方式:命名卷和绑定挂载。命名卷由 Docker 管理,存在/var/lib/docker/volumes/下,适合数据库这类不需要直接访问文件的场景。绑定挂载把宿主机目录直接映射进容器,适合开发时改代码即时生效。
# 命名卷:创建 my-vol,挂到容器的 /app docker volume create my-vol docker run -d \ --name devtest \ -v my-vol:/app \ nginx:latest # 绑定挂载:把当前目录的 html 挂到 nginx 的网页目录 docker run -d \ --name devtest \ -v "$(pwd)"/html:/usr/share/nginx/html \ nginx:latest逻辑说明:-v my-vol:/app里my-vol是卷名,Docker 会自动创建;-v "$(pwd)"/html:/usr/share/nginx/html里宿主机路径必须是绝对路径,$(pwd)展开当前目录。绑定挂载的权限问题很常见——容器内进程的 UID 和宿主机文件属主不一致时会写不进去,解决办法是-u指定 UID 或者调整宿主机目录权限。
参数说明:docker volume ls列出所有卷,docker volume inspect my-vol看卷的挂载点,docker volume rm my-vol删卷。绑定挂载加:ro可以只读挂载,比如-v "$(pwd)"/config:/etc/nginx/conf.d:ro。
5.2 非 root 运行与最小化镜像
这份指南的安全部分给了两条原则:最小化镜像和非 root 运行。Dockerfile 示例用node:18-alpine做基础镜像,USER node切换非 root 用户:
FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production USER node CMD ["node", "server.js"]逻辑说明:alpine镜像体积只有几十 MB,比node:18小一个数量级,但 alpine 用的是 musl libc,某些依赖 glibc 的 npm 包会出问题,构建时报错就换node:18-slim。npm ci比npm install更适合 CI 环境,它严格按package-lock.json安装,不会改锁文件。USER node必须在COPY和RUN之后,否则后续文件属主会变成 node,可能导致权限问题。
参数说明:WORKDIR创建并切换目录,后续COPY和RUN都在这个目录下;COPY package*.json ./先只拷依赖清单,利用 Docker 层缓存,代码改了不用重装依赖;--only=production跳过 devDependencies。
提示:
docker scan可以扫描镜像漏洞,但需要登录 Docker Hub。替代方案是trivy image 镜像名,本地跑不需要账号。
6. 排查清单与进阶路径:那些文档没写的翻车点
6.1 五条血泪踩坑记录
现象:docker run hello-world报Cannot connect to the Docker daemon。原因:Docker 服务没启动,或者当前用户不在 docker 组且没加 sudo。 解决:sudo systemctl start docker启动服务,sudo systemctl enable docker设开机自启;权限问题按第 2.3 节加组后重新登录。
现象:docker pull卡住或超时。原因:默认镜像仓库在国内访问不稳定。 解决:配置镜像加速器,编辑/etc/docker/daemon.json加registry-mirrors,然后sudo systemctl restart docker。注意加速器地址会失效,用之前先确认可用性。
现象:docker compose up后 WordPress 报数据库连接错误。原因:MySQL 8.0 初始化需要时间,WordPress 启动太快连不上;或者WORDPRESS_DB_HOST写成了localhost而不是服务名db。 解决:等几十秒刷新页面;检查 compose 文件里 host 是否为服务名;docker compose logs db确认 MySQL 是否 ready。
现象:绑定挂载的目录在容器里看不到文件。原因:SELinux 或 AppArmor 拦截,或者宿主机路径写成了相对路径。 解决:Ubuntu 上检查 AppArmor 状态;挂载路径用$(pwd)展开成绝对路径;SELinux 系统加:z或:Z标签。
现象:docker build时npm install失败,报网络错误。原因:构建容器内的 DNS 配置和宿主机不一致,或者基础镜像的包管理器源不可达。 解决:在 Dockerfile 里换源,或者构建时加--network=host让构建容器用宿主机网络。
6.2 从单机到编排的进阶路线
这份指南最后给了学习路径:官方文档、Play with Docker 实验环境、网络模式、Compose、Kubernetes、CI/CD。按我的经验,顺序应该是先把docker run和docker compose用熟,再碰网络模式。bridge 模式是默认,host 模式让容器直接用宿主机网络(性能好但端口冲突风险高),none 模式适合完全隔离的场景。Kubernetes 不用急着上,单机 compose 能跑通三五个服务之后,再理解 Pod、Service、Deployment 会顺很多。
验证自己是否真的掌握了,可以试一个具体技巧:用docker compose起一套 WordPress,然后故意把db服务的卷删掉,观察数据丢失的过程,再用绑定挂载把 WordPress 的wp-content目录映射到宿主机,改主题文件即时生效。这一套走下来,数据卷和绑定挂载的区别就不用背了。
从那以后我每次写 compose 文件,都强制先跑一遍docker compose config检查语法,再up -d,最后logs -f盯一分钟——这个习惯帮我省掉了至少三次“以为起来了其实在反复重启”的排查时间。希望帮到你。
本文还有配套的精品资源,点击获取