简介:《Docker基础入门指南》面向具备一定计算机基础、希望从零掌握容器技术的开发者与运维初学者,帮助解决环境搭建繁琐、部署流程不统一等入门痛点。资源包共1个PDF文件,约696KB,内容以图文与命令示例为主,便于随时查阅与动手练习。文档从Docker概念与容器、虚拟机对比讲起,梳理镜像、容器、仓库三大核心概念,并覆盖Windows、macOS及Ubuntu平台的安装配置;基础操作部分涵盖拉取镜像、运行与查看容器、进入容器内部、停止删除等常用命令。实战环节通过Nginx服务器部署、挂载本地目录、编写Dockerfile构建Python应用镜像等案例,串联镜像管理与Web应用部署流程,同时给出权限配置、镜像加速、数据持久化等常见问题解决思路及学习资源推荐。目前已有126人学习,适合按章节顺序边学边练,快速建立容器化开发的完整认知。
1. 从一份 Docker 基础入门指南说起:为什么你装完就卡在第一步
很多人第一次接触容器技术,是从一份 Docker 基础入门指南.pdf 开始的。照着文档敲docker run hello-world,结果终端要么报Cannot connect to the Docker daemon,要么在 Windows 上弹出一句virtualization support not detected docker desktop failed to start,直接卡死在第一步。这不是你笨,而是容器技术横跨了内核、网络、文件系统三层,任何一层没对齐,命令就跑不起来。
这篇东西不讲概念史,只解决一件事:让你在一台干净的机器上,把 Docker 装好、跑起来、能拉镜像、能起容器、能排错,最后知道这套东西值不值得往生产环境推。适合两类人:刚接手服务器、被要求「用容器部署一下」的后端和运维新手;以及用过docker run但一遇到网络不通、权限报错就抓瞎的熟手。下面按「装 → 跑 → 配 → 排 → 进阶」的顺序推,每一步都给能直接抄的命令和参数解释。
2. 装 Docker 之前先想清楚:三种安装路径怎么选
2.1 为什么 Linux、Windows、macOS 的安装逻辑完全不同
Docker 本质是 Linux 内核能力的封装:namespace 做隔离,cgroup 做资源限制,UnionFS 做分层镜像。所以它在 Linux 上是原生的,在 Windows 和 macOS 上必须借助一层虚拟机。这就决定了三条安装路径的差异。
Linux 上装的是 Docker Engine,直接跑在宿主机内核上,性能损耗接近零,是生产环境唯一推荐的方式。Ubuntu、CentOS、Debian 都走这条路。Windows 上装的是 Docker Desktop,它内部起一个 WSL2 或 Hyper-V 虚拟机,你的容器其实跑在虚拟机里,所以会碰到virtualization support not detected这类问题——不是 Docker 坏了,是 BIOS 里的虚拟化开关没开。macOS 同理,Docker Desktop 跑在一个轻量 Linux VM 里。
选型结论很直接:服务器一律 Linux 原生安装;本地开发用 Windows 或 macOS 的 Docker Desktop 图省事;如果 Windows 上要做接近生产的验证,优先开 WSL2 后端而不是 Hyper-V。
2.2 Ubuntu 上装 Docker Engine 的最小命令序列
下面这套是 Ubuntu 22.04/24.04 上最稳的装法,用官方仓库而不是apt install docker.io,因为发行版自带的版本往往落后好几个大版本。
# 1. 卸载可能存在的旧版本,避免冲突 sudo apt remove docker docker-engine docker.io containerd runc # 2. 装依赖:ca证书、curl、gnupg sudo apt update sudo apt install -y ca-certificates curl gnupg # 3. 添加官方 GPG 密钥,用于校验包来源 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 # 4. 写入软件源,注意 $(dpkg --print-architecture) 自动匹配 amd64/arm64 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 # 5. 安装引擎、CLI、containerd 和 compose 插件 sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin # 6. 验证:能打印版本且守护进程在跑 sudo systemctl status docker docker version逻辑说明:第 3 步的 GPG 密钥是防止你从被篡改的源拉到恶意包,这一步别省。第 4 步用VERSION_CODENAME自动取jammy或noble,避免手写错代号导致apt update报 404。第 5 步一次装齐五个包,docker-compose-plugin让你能用docker compose(注意是空格不是横杠)这个新语法。
参数说明:-m 0755是给目录设权限,--dearmor把 ASCII 密钥转成二进制格式,新版 apt 要求这样。装完默认只有 root 能调 Docker,普通用户要加进 docker 组,见 2.3。
2.3 装完必做的两件事:免 sudo 和换镜像源
第一件,把当前用户加进 docker 组,否则每条命令都要sudo,脚本里会很难受:
sudo usermod -aG docker $USER # 退出重新登录,或执行下面这行让组生效 newgrp docker # 验证:不加 sudo 也能跑 docker ps第二件,国内拉镜像慢是常态,配一个镜像加速器。编辑/etc/docker/daemon.json:
{ "registry-mirrors": [ "https://docker.m.daocloud.io", "https://dockerproxy.com" ], "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" } }逻辑说明:registry-mirrors是拉取镜像时的备用源,Docker 会按顺序尝试。log-driver和log-opts是给容器日志做轮转,不然一个话痨容器几天就能把磁盘写满,这是血泪经验。改完执行sudo systemctl daemon-reload && sudo systemctl restart docker生效。
参数说明:max-size: 100m表示单个日志文件到 100MB 就切,max-file: 3表示最多留 3 个,总共不超过 300MB。镜像源地址会失效,用之前先确认能通,别照抄一个早就挂掉的地址然后怀疑人生。
3. 跑起第一个容器:run、exec、网络三件套
3.1 docker run 的参数到底在控制什么
docker run是入门最高频也最容易用错的命令。它的参数分四类:镜像与命令、端口映射、存储挂载、运行模式。看一个典型例子:
docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=yourpass \ -v /data/mysql:/var/lib/mysql \ --restart unless-stopped \ mysql:8.0逻辑说明:-d让容器后台运行,不加它你的终端会被占住。--name给容器起名,方便后续docker exec和docker stop引用,不然只能用随机 ID。-p 3306:3306是端口映射,格式是「宿主机端口:容器端口」,左边是你从外面访问的端口,右边是容器内服务监听的端口,写反了就连不上。-e注入环境变量,MySQL 镜像靠MYSQL_ROOT_PASSWORD初始化 root 密码,不设这个变量容器会直接退出。-v把宿主机目录挂进容器,数据库数据必须挂出来,否则容器一删数据全没。--restart unless-stopped让容器随 Docker 启动而自启,除非你手动停过它。
参数说明:mysql:8.0里的8.0是标签,不写标签默认拉latest,生产环境千万别用latest,因为下次拉可能就变了个大版本,直接把你搞翻车。
3.2 进容器排查:exec 和 run 的区别
容器起来了但服务没通,第一反应是进去看。这里有个高频混淆点:docker exec和docker run都能给你一个 shell,但语义完全不同。
# 进入正在运行的容器,开一个交互式 bash docker exec -it mysql8 bash # 如果容器里没有 bash,用 sh docker exec -it mysql8 sh # 在运行中的容器里执行单条命令,不进交互 docker exec mysql8 mysql -uroot -p -e "show databases;" # 用一次性容器做临时任务,跑完即删 docker run --rm -it alpine sh逻辑说明:exec是「进入一个已经在跑的容器」,前提是容器状态为 Up,容器停了会报is not running。run是「用镜像新建一个容器」,--rm表示退出后自动删除,适合做临时调试,不留垃圾。-it是-i(保持标准输入)加-t(分配伪终端)的合写,少了-t你敲命令会没有回显,少了-i交互程序会立刻退出。
参数说明:alpine是个 5MB 左右的极简镜像,拿来测网络、测 DNS 特别方便,比动辄几百 MB 的 ubuntu 镜像快得多。
3.3 容器网络不通的三种典型场景
网络是 Docker 入门最大的玄学区。容器之间、容器到宿主机、容器到外网,三层的规则不一样。默认情况下 Docker 会创建bridge、host、none三个网络,docker run不加--network就走 bridge。
# 查看现有网络 docker network ls # 创建自定义 bridge 网络,容器间可用名字互相解析 docker network create mynet # 两个容器接入同一网络,直接用容器名通信 docker run -d --name app --network mynet nginx docker run -d --name db --network mynet mysql:8.0 # 此时在 app 容器里 ping db 是通的,因为自定义网络自带 DNS逻辑说明:默认 bridge 网络里的容器只能用 IP 互相访问,不能用容器名,这是很多人「明明都起来了却连不上」的根因。自定义 bridge 网络内置了 DNS 解析,容器名就是主机名,这是推荐做法。容器访问宿主机服务,Linux 上用宿主机在 bridge 上的网关 IP(通常是 172.17.0.1),或者用--add-host=host.docker.internal:host-gateway显式加一条解析。
参数说明:--network mynet指定网络,不写就是默认 bridge。排查网络先用docker exec -it 容器名 ping 目标,再docker exec -it 容器名 cat /etc/resolv.conf看 DNS 配置,最后docker network inspect mynet看容器有没有真的接进去。
4. 用 Compose 把多容器项目一次拉起来
4.1 为什么单条 run 命令撑不住真实项目
一个 Web 项目通常有应用、数据库、缓存、反向代理四五个组件,每个都要配端口、挂载、环境变量、依赖顺序。用docker run一条条敲,不仅长,还没法版本管理,换台机器就得重来。Compose 用一个 YAML 文件描述整套服务,docker compose up -d一条命令全起来,这是从入门到能干活的分水岭。
4.2 一份能直接跑的 compose 文件
下面这份描述了一个 Nginx + MySQL + Redis 的最小组合,字段都是高频必用的:
services: web: image: nginx:1.27 ports: - "8080:80" volumes: - ./html:/usr/share/nginx/html:ro depends_on: - db networks: - backend db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: rootpass MYSQL_DATABASE: appdb volumes: - dbdata:/var/lib/mysql networks: - backend cache: image: redis:7-alpine command: redis-server --appendonly yes volumes: - cachedata:/data networks: - backend volumes: dbdata: cachedata: networks: backend: driver: bridge逻辑说明:services下每个键就是一个容器。depends_on只保证启动顺序(先起 db 再起 web),不保证 db 里的 MySQL 已经初始化完成,这是新手最容易误解的点,真正的健康检查要用healthcheck。volumes顶层声明命名卷,下面用dbdata:/var/lib/mysql引用,命名卷由 Docker 管理,比绑定宿主机目录更省心。networks顶层声明后,各服务用networks: [backend]接入,同一网络内服务名即主机名。
参数说明:./html:/usr/share/nginx/html:ro里的:ro表示只读挂载,防止容器改宿主机文件。redis-server --appendonly yes开启 AOF 持久化,不然 Redis 重启数据就没了。nginx:1.27锁版本,别用 latest。
4.3 compose 的常用操作和日志排查
# 后台启动全部服务 docker compose up -d # 只看某个服务的日志,实时跟随 docker compose logs -f web # 重新构建并重启某个服务(改了配置后) docker compose up -d --build web # 停掉并删除容器、网络,但保留命名卷 docker compose down # 连卷一起删,慎用,数据会没 docker compose down -v # 查看各服务状态 docker compose ps逻辑说明:logs -f是排查启动失败的第一入口,容器起不来时先看日志,八成能看到端口占用、密码没设、配置文件语法错这类明确原因。down默认保留命名卷,这是有意的设计,防止你手滑删库。down -v才会连数据一起清,执行前想清楚。
参数说明:-d是 detached,后台运行;--build强制重新构建镜像,改了 Dockerfile 或代码后必须加,否则用的还是旧镜像。
5. 避坑与排查:那些让新手卡半天的报错
5.1 现象:Cannot connect to the Docker daemon
原因:Docker 守护进程没启动,或者当前用户没权限访问 socket。在 Linux 上多半是服务没起,在 Windows/macOS 上多半是 Docker Desktop 没开。
解决:Linux 上sudo systemctl start docker并sudo systemctl enable docker设为开机自启;权限问题执行sudo usermod -aG docker $USER后重新登录。Windows 上确认 Docker Desktop 托盘图标是运行状态,报failed to connect to the docker api at npipe基本就是 Desktop 没起来。
5.2 现象:Windows 上 virtualization support not detected
原因:BIOS/UEFI 里的 CPU 虚拟化(Intel VT-x 或 AMD-V)没开,或者 Hyper-V/WSL2 组件没启用。Docker Desktop 需要这层虚拟化才能跑 Linux 虚拟机。
解决:重启进 BIOS 打开虚拟化开关;Windows 功能里勾选「虚拟机平台」和「适用于 Linux 的 Windows 子系统」;命令行执行wsl --update更新 WSL2 内核。三条都做完再重启 Docker Desktop。
5.3 现象:docker 权限错误,普通用户跑不了
原因:/var/run/docker.sock属主是 root:docker,当前用户不在 docker 组里。
解决:sudo usermod -aG docker $USER后必须重新登录(newgrp docker只对当前 shell 生效)。注意 docker 组等价于 root 权限,生产机上别随便加人。
5.4 现象:镜像下载慢或拉取超时
原因:默认从 Docker Hub 拉,跨境链路不稳定。
解决:配daemon.json里的registry-mirrors,改完重启 Docker。如果某个镜像源失效,换一个再试,别死磕一个地址。拉大镜像时用docker pull 镜像:标签单独拉,能看到进度,比run时卡住强。
5.5 现象:容器起来了但端口访问不通
原因:端口映射写反、宿主机防火墙没放行、服务在容器内只监听了 127.0.0.1。
解决:先docker port 容器名确认映射关系;再docker exec -it 容器名 ss -tlnp看服务监听地址,如果监听的是 127.0.0.1 而不是 0.0.0.0,容器外就访问不到,得改服务配置;最后检查宿主机防火墙和云服务器安全组。
6. 进阶:把镜像做小、把环境做稳的几个具体技巧
镜像体积直接决定部署速度和攻击面。一个常见误区是拿ubuntu当基础镜像,装完依赖动辄 1GB 起。我一般用多阶段构建,把编译环境和运行环境分开:
# 阶段一:构建,装全量依赖 FROM python:3.12-slim AS builder WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir --prefix=/install -r requirements.txt # 阶段二:运行,只拷成品 FROM python:3.12-slim WORKDIR /app COPY --from=builder /install /usr/local COPY . . EXPOSE 8000 CMD ["python", "app.py"]逻辑说明:--prefix=/install把依赖装到一个独立目录,第二阶段用COPY --from=builder只拷这个目录,编译工具链全留在第一阶段被丢弃。--no-cache-dir不保留 pip 缓存,能省几十到上百 MB。最终镜像通常能比单阶段小一半以上。
参数说明:python:3.12-slim比完整版小很多,又比alpine兼容性好(alpine 用 musl libc,某些 C 扩展会编译失败)。选基础镜像时,slim 是多数场景的平衡点。
再给一个验证镜像是否干净的习惯:构建完执行docker history 镜像名看每层大小,找出异常大的层;用docker run --rm -it 镜像名 sh进去手动跑一遍启动命令,确认没有隐藏的运行时依赖缺失。这套动作我每次发版前都做,能挡掉大部分「本地好好的、上线就崩」的问题。
最后说个习惯:所有docker run里用到的端口、卷、环境变量,都写进 compose 文件或脚本,别留在终端历史里。容器这东西,能复现才有价值,靠记忆敲命令迟早翻车。希望帮到你。
本文还有配套的精品资源,点击获取