Docker 从入门到精通

📅 发布时间:2026/7/10 7:55:16 👁️ 浏览次数:
Docker 从入门到精通
前言Docker 是一个开源的容器化平台它让开发者能够将应用程序及其依赖打包成一个轻量级、可移植的容器然后在任何支持 Docker 的环境开发、测试、生产中运行。容器技术正在重塑软件开发、交付和运维的方式。本文将带您从零开始逐步掌握 Docker 的核心概念、命令操作、高级特性以及生产环境的最佳实践无论您是初学者还是有一定经验的开发者都能从中获益。1. Docker 简介1.1 什么是容器容器是一种轻量级的虚拟化技术它允许在操作系统级别隔离进程每个容器运行在自己的独立环境中拥有自己的文件系统、网络空间、进程树等。与传统的虚拟机相比容器共享宿主机的内核不需要为每个应用运行完整的操作系统因此启动快、资源利用率高。特性虚拟机容器启动速度分钟级秒级内核每个 VM 有独立内核共享宿主机内核资源占用高GB 级别低MB 级别隔离性强硬件级隔离较强进程级隔离交付一致性镜像大环境一致镜像小环境一致1.2 Docker 的优势环境一致性消除“在我电脑上能运行”的问题开发、测试、生产环境完全一致。快速部署容器秒级启动便于弹性伸缩。资源高效更密集的部署节省硬件成本。持续集成与交付Docker 镜像可作为标准交付物与 CI/CD 流程无缝集成。版本控制镜像分层可以追踪每个变更。1.3 Docker 的架构Docker 采用客户端-服务器C/S架构主要组件包括Docker 客户端docker命令与用户交互将指令发送给 Docker 守护进程。Docker 守护进程dockerd负责管理容器、镜像、网络、卷等监听 Docker API 请求。Docker 镜像只读模板包含运行应用所需的文件系统、依赖和配置。Docker 容器镜像的运行实例可读写。Docker 仓库如 Docker Hub存储和分发镜像。2. 安装 Docker2.1 在 Linux 上安装以 Ubuntu 为例bash# 卸载旧版本 sudo apt-get remove docker docker-engine docker.io containerd runc # 更新软件包索引 sudo apt-get update # 安装依赖 sudo apt-get install ca-certificates curl gnupg lsb-release # 添加 Docker 官方 GPG 密钥 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg # 设置稳定版仓库 echo \ deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null # 安装 Docker Engine sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io # 启动 Docker 并设置开机自启 sudo systemctl start docker sudo systemctl enable docker # 验证安装 sudo docker run hello-world2.2 在 Windows 上安装推荐使用 Docker Desktop for Windows它提供了图形化界面和与 WSL 2 的集成。下载地址Docker Desktop安装后可在任务栏看到 Docker 鲸鱼图标打开终端PowerShell 或 CMD即可使用docker命令。2.3 在 macOS 上安装同样使用 Docker Desktop for Mac下载安装后启动即可。2.4 配置镜像加速器国内访问 Docker Hub 可能较慢可配置国内镜像加速器如阿里云、中科大。在 Linux 上编辑/etc/docker/daemon.json若无则新建json{ registry-mirrors: [https://你的加速器地址] }重启 Dockersudo systemctl restart docker。3. Docker 基础命令3.1 镜像管理搜索镜像docker search nginx拉取镜像docker pull nginx:latest列出本地镜像docker images删除镜像docker rmi nginx:latest需先删除依赖的容器标记镜像docker tag nginx:latest myrepo/nginx:v1推送镜像到仓库docker push myrepo/nginx:v1保存镜像为文件docker save -o nginx.tar nginx:latest从文件加载镜像docker load -i nginx.tar3.2 容器生命周期运行容器docker run -d --name mynginx -p 8080:80 nginx:latest-d后台运行--name指定名称-p端口映射格式宿主机端口:容器端口列出运行中的容器docker ps列出所有容器包括停止的docker ps -a停止容器docker stop mynginx启动已停止的容器docker start mynginx重启容器docker restart mynginx删除容器docker rm mynginx可加-f强制删除运行中的进入容器内部docker exec -it mynginx bash需容器支持 bash查看容器日志docker logs mynginx可加-f实时跟踪查看容器内进程docker top mynginx查看容器详细信息docker inspect mynginx3.3 资源限制限制内存docker run -d --memory256m nginx限制 CPUdocker run -d --cpus1.5 nginx使用 1.5 个核心限制 CPU 份额--cpu-shares 512相对权重3.4 交互式容器示例bashdocker run -it --name test ubuntu:20.04 bash进入容器后可以执行命令退出exit后容器停止。4. Docker 镜像深入4.1 镜像分层与 UnionFSDocker 镜像由一系列只读层组成每一层代表一组文件系统的变更如添加文件、修改配置。这些层通过联合文件系统UnionFS如 Overlay2叠加在一起形成最终的根文件系统。当容器运行时会在这些只读层之上添加一个可写层容器层实现写时复制Copy-on-Write。这种分层结构的好处是镜像复用不同镜像可以共享相同的基础层。节省存储只需存储变化的部分。加速推送和拉取只传输新增的层。4.2 通过 commit 创建镜像bash# 运行一个基础容器做一些修改 docker run -it ubuntu:20.04 bash # 在容器内安装 curl apt update apt install curl -y exit # 提交容器生成新镜像 docker commit -m Added curl 容器ID或名称 myubuntu:withcurl但不推荐频繁使用 commit因为这样的镜像缺乏可重复性和透明度应优先使用 Dockerfile。4.3 Dockerfile 详解Dockerfile 是一个文本文件包含构建镜像所需的指令。以下是一个简单的 Node.js 应用示例dockerfile# 指定基础镜像 FROM node:14-alpine # 设置工作目录 WORKDIR /app # 复制 package.json 和 package-lock.json COPY package*.json ./ # 安装依赖 RUN npm install --production # 复制源代码 COPY . . # 暴露端口 EXPOSE 3000 # 定义启动命令 CMD [node, app.js]常用指令FROM指定基础镜像必须是第一条指令。RUN在构建过程中执行命令如安装软件每一条 RUN 都会创建一个新层。COPY将文件从构建上下文复制到镜像中。ADD类似 COPY但支持 URL 和自动解压 tar 文件。CMD容器启动时的默认命令可以被docker run后的命令覆盖。Dockerfile 中只能有一条 CMD。ENTRYPOINT配置容器启动时的入口程序与 CMD 配合使用。CMD 可以作为参数传递给 ENTRYPOINT。示例ENTRYPOINT [python]CMD [app.py]→ 启动时运行python app.pyENV设置环境变量。ARG定义构建时的变量仅在构建时有效。WORKDIR设置工作目录后续指令RUN, CMD, ENTRYPOINT, COPY, ADD会在此目录执行。USER指定运行容器的用户或 UID。VOLUME创建挂载点用于数据持久化。EXPOSE声明容器运行时监听的端口但不实际映射。HEALTHCHECK定义容器健康检查命令。ONBUILD当该镜像作为其他镜像的基础镜像时触发的指令。LABEL添加元数据。多阶段构建多阶段构建允许在一个 Dockerfile 中使用多个 FROM 语句每个阶段可以基于不同的基础镜像最终只将需要的产物复制到最终镜像有效减小镜像体积。示例构建 Go 应用dockerfile# 构建阶段 FROM golang:1.17-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go build -o myapp . # 最终阶段 FROM alpine:latest WORKDIR /root/ COPY --frombuilder /app/myapp . EXPOSE 8080 CMD [./myapp]镜像优化建议选择轻量级基础镜像如 alpine。合并 RUN 指令减少层数RUN apt update apt install -y package1 package2 rm -rf /var/lib/apt/lists/*。使用.dockerignore忽略不必要的文件。多阶段构建。不要将敏感信息如密码写入镜像。4.4 构建镜像bashdocker build -t myapp:1.0 . # 注意最后的 . 表示构建上下文路径5. Docker 数据管理容器是无状态的当容器删除后其内部数据也会丢失。Docker 提供了多种方式持久化数据。5.1 数据卷Volume数据卷是 Docker 管理的目录存在于宿主机/var/lib/docker/volumes/下独立于容器生命周期。创建数据卷docker volume create mydata查看数据卷docker volume ls查看详情docker volume inspect mydata删除数据卷docker volume rm mydata使用数据卷bash# 运行容器并挂载数据卷若卷不存在则自动创建 docker run -d -v mydata:/app/data --name app1 nginx-v或--mount均可推荐使用--mount更明确bashdocker run -d --mount sourcemydata,target/app/data nginx5.2 绑定挂载Bind Mount将宿主机上的目录或文件挂载到容器中宿主机路径必须是绝对路径。bash# 将当前目录下的 html 挂载到容器 /usr/share/nginx/html docker run -d -p 8080:80 -v $(pwd)/html:/usr/share/nginx/html nginx或使用--mountbashdocker run -d -p 8080:80 --mount typebind,source$(pwd)/html,target/usr/share/nginx/html nginx绑定挂载适合开发环境可以实时同步代码。5.3 tmpfs 挂载tmpfs 挂载将数据存储在内存中仅临时使用容器停止后数据丢失。bashdocker run -d --tmpfs /tmp --name app nginx或使用--mountbashdocker run -d --mount typetmpfs,destination/tmp nginx5.4 数据卷容器创建一个专门用于存储数据的容器其他容器通过--volumes-from共享其数据卷。bash# 创建数据容器挂载一个卷 docker create -v /dbdata --name dbstore ubuntu /bin/true # 其他容器使用 --volumes-from 共享该数据卷 docker run -d --volumes-from dbstore --name app1 nginx5.5 备份与恢复备份数据卷bash# 创建一个临时容器将数据卷挂载打包卷内容到宿主机 docker run --rm -v mydata:/volume -v $(pwd):/backup alpine tar czf /backup/mydata.tar.gz -C /volume .恢复数据卷bashdocker run --rm -v mydata:/volume -v $(pwd):/backup alpine tar xzf /backup/mydata.tar.gz -C /volume6. Docker 网络Docker 网络让容器间可以互相通信并与外界隔离或开放。6.1 网络模式bridge默认模式容器通过虚拟网桥连接到宿主机分配独立的 IP。host容器直接使用宿主机的网络栈没有网络隔离。none容器没有网络接口。container容器共享另一个容器的网络命名空间。查看网络docker network ls6.2 自定义 bridge 网络默认的 bridge 网络docker0中容器可以通过 IP 通信但无法通过容器名解析。自定义 bridge 网络支持自动 DNS 解析容器间可通过容器名直接访问。bash# 创建自定义网络 docker network create mynet # 运行两个容器在同一网络 docker run -d --name web --network mynet nginx docker run -it --name test --network mynet alpine sh # 在 test 容器中 ping web应能解析 / # ping web6.3 端口映射将容器端口映射到宿主机使外部可以访问bashdocker run -d -p 8080:80 nginx-p可以多次使用映射多个端口也可指定 IP-p 127.0.0.1:8080:80。6.4 容器间通信通过 IP 通信同一网络内的容器可以通过分配的 IP 直接通信。通过容器名通信仅限自定义网络默认 bridge 不支持。link 机制旧式--link web:web可在默认 bridge 中为容器添加别名但不推荐使用应使用自定义网络。6.5 网络驱动overlay用于跨主机的容器通信需要 Swarm 或 Kubernetes 配合。macvlan为容器分配 MAC 地址使其看起来像物理设备便于与物理网络集成。7. Docker ComposeDocker Compose 是一个用于定义和运行多容器 Docker 应用的工具。通过一个 YAML 文件docker-compose.yml配置服务、网络和卷然后使用一条命令启动所有服务。7.1 安装 ComposeLinux从 GitHub 下载二进制文件。Docker Desktop 已自带 Compose。验证docker-compose --version7.2 docker-compose.yml 编写以一个 WordPress 应用为例yamlversion: 3.8 services: db: image: mysql:5.7 container_name: wordpress_db restart: always environment: MYSQL_ROOT_PASSWORD: rootpassword MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress volumes: - db_data:/var/lib/mysql networks: - wordpress-net wordpress: depends_on: - db image: wordpress:latest container_name: wordpress_app restart: always ports: - 8000:80 environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_NAME: wordpress volumes: - wp_data:/var/www/html networks: - wordpress-net volumes: db_data: wp_data: networks: wordpress-net:version指定 Compose 文件格式的版本与 Docker 引擎版本对应。services定义多个服务容器。image使用的镜像。build若本地构建指定 Dockerfile 路径。container_name自定义容器名。restart重启策略。environment环境变量。volumes挂载卷或绑定挂载。ports端口映射。depends_on服务依赖顺序。networks连接的网络。volumes和networks顶层声明使用的卷和网络。7.3 Compose 常用命令启动所有服务docker-compose up -d-d 后台运行停止并删除容器、网络docker-compose down查看服务日志docker-compose logs -f列出服务状态docker-compose ps在某个服务容器中执行命令docker-compose exec wordpress bash构建或重建服务docker-compose build查看配置docker-compose config7.4 环境变量与扩展可以在.env文件中定义变量然后在docker-compose.yml中引用${VAR_NAME}。还支持使用extends字段继承配置或使用 YAML 锚点复用。7.5 多容器应用示例上面已经展示了 WordPress MySQL 的例子。部署时只需bashdocker-compose up -d然后访问http://宿主机IP:8000即可。8. Docker SwarmSwarm 是 Docker 原生的容器编排工具可以将多个 Docker 主机组成一个集群以提供服务部署、伸缩、负载均衡等能力。8.1 Swarm 初始化bash# 在管理节点上初始化 Swarm docker swarm init --advertise-addr 管理节点IP # 输出类似以下命令用于工作节点加入 Swarm docker swarm join --token TOKEN 管理节点IP:23778.2 节点管理查看节点列表docker node ls提升节点为管理节点docker node promote node降级为工作节点docker node demote node离开 Swarm在工作节点执行docker swarm leave管理节点加--force。8.3 服务创建与伸缩Swarm 中部署的最小单位是服务service。bash# 创建 nginx 服务3 个副本映射端口 80 docker service create --name web --replicas 3 -p 80:80 nginx # 查看服务列表 docker service ls # 查看服务详情 docker service ps web # 伸缩服务 docker service scale web5 # 更新服务镜像版本 docker service update --image nginx:1.21 web # 删除服务 docker service rm web8.4 网络与负载均衡Swarm 会自动为服务创建一个 overlay 网络使得跨主机的容器可以通信。当在服务上发布端口时-p每个节点的该端口都会接收请求并由 Swarm 内置的负载均衡器分发到容器。8.5 滚动更新与回滚bash# 执行滚动更新每次更新 2 个副本间隔 10 秒 docker service update --image nginx:1.21 --update-parallelism 2 --update-delay 10s web # 如果更新失败可以回滚 docker service rollback web8.6 秘钥与配置管理Swarm 支持存储敏感信息如密码为 secret以及配置文件为 config。bash# 创建 secret echo mypassword | docker secret create db_password - # 创建 config docker config create app_conf config.yml # 在服务中使用 secret docker service create --name app --secret db_password --config sourceapp_conf,target/config/app.yml nginx9. Docker 与 KubernetesKubernetesK8s是目前最流行的容器编排平台功能比 Swarm 更强大。Docker 与 K8s 集成密切但 K8s 已逐步移除对 Docker 的直接支持转向 containerd 等 CRI 运行时。不过我们仍可以使用 Docker 构建镜像然后在 K8s 集群中运行。9.1 Kubernetes 简介K8s 提供 Pod一组容器、Deployment管理 Pod 副本、Service服务发现与负载均衡、ConfigMap、Secret 等资源并支持自动伸缩、滚动更新、自愈等。9.2 搭建本地集群使用 kind 或 minikube使用 kindKubernetes in Dockerbash# 安装 kind curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.14.0/kind-linux-amd64 chmod x ./kind sudo mv ./kind /usr/local/bin/kind # 创建集群 kind create cluster使用 minikubebashminikube start --driverdocker9.3 部署应用到 K8s编写一个 Deployment 和 Service 的 YAML 文件nginx-deploy.yamlyamlapiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx-service spec: type: NodePort selector: app: nginx ports: - port: 80 targetPort: 80 nodePort: 30080应用配置bashkubectl apply -f nginx-deploy.yaml # 查看 Pod kubectl get pods # 查看 Service kubectl get svc # 访问服务NodePort 方式http://任意节点IP:300809.4 与 Docker Compose 对比Compose 适用于单机多容器开发测试。K8s 适用于生产级集群具备高可用、自动伸缩等高级特性。工具如 Kompose 可以将 Compose 文件转换为 K8s 资源。10. Docker 安全容器安全涉及多个层面镜像安全、运行时隔离、主机加固等。10.1 容器隔离机制Docker 利用 Linux 内核的以下特性实现隔离命名空间Namespaces为每个容器提供独立的视图PID、网络、挂载、UTS、IPC、用户。控制组Cgroups限制和监控资源使用CPU、内存、磁盘 I/O 等。能力Capabilities将 root 权限细粒度划分容器默认只拥有部分能力如CAP_NET_BIND_SERVICE。10.2 安全加固实践以非 root 用户运行容器在 Dockerfile 中添加USER appuser避免容器内进程拥有过高权限。只读根文件系统docker run --read-only防止容器内写入篡改。删除多余能力--cap-dropALL --cap-add必要能力。限制系统调用seccomp使用自定义 seccomp 配置文件限制容器的系统调用。使用 AppArmor 或 SELinux为容器设置强制访问控制策略。禁止特权容器--privileged会赋予所有能力并访问所有设备应尽量避免。资源限制防止 DoS 攻击限制 CPU、内存。镜像安全使用可信基础镜像如官方镜像。定期扫描镜像漏洞docker scan或 Trivy。最小化镜像体积减少攻击面。10.3 Docker 守护进程安全配置保护 Docker 套接字默认docker.sock拥有 root 权限不要随意挂载到容器内。开启 TLS 认证如果暴露 Docker API应配置 TLS 证书。使用内容信任Docker Content Trust对镜像签名和验证。10.4 使用 seccomp 示例创建一个 seccomp 配置文件seccomp-profile.json禁用某些系统调用然后运行容器bashdocker run --security-opt seccompseccomp-profile.json nginx11. 高级话题11.1 Docker 存储驱动Docker 使用存储驱动管理镜像层和容器可写层。常见存储驱动overlay2目前推荐的驱动性能好支持所有 Linux 发行版。aufs较早的驱动但未合入 Linux 主线。devicemapper使用快照性能较差不推荐。btrfs/zfs特定文件系统驱动。查看当前存储驱动docker info | grep Storage Driver11.2 容器运行时runc符合 OCI 规范的容器运行时Docker 默认使用。containerd高级容器运行时管理容器生命周期Docker 将 containerd 作为底层组件。CRI-O专门为 Kubernetes 实现的 OCI 运行时。11.3 Docker 远程 APIDocker 守护进程可以监听 HTTP 端口供远程客户端调用。配置方法在/etc/docker/daemon.json中添加hosts: [tcp://0.0.0.0:2375, unix:///var/run/docker.sock]然后重启 Docker。注意暴露端口需配置安全措施否则易被攻击。11.4 调试容器docker exec进入容器。docker logs查看日志。docker inspect查看容器详细信息。docker diff查看容器文件系统变化。docker events实时查看 Docker 事件。nsenter进入容器的命名空间需要宿主机 root 权限。11.5 容器监控docker stats查看容器实时资源使用。cAdvisorGoogle 开源的容器监控工具收集资源利用和性能数据。Prometheus Grafana建立完善的监控体系。Docker 插件如 sysdig。11.6 Docker 与 CI/CD以 GitLab CI 为例.gitlab-ci.yml中包含构建和推送镜像的步骤yamlstages: - build - deploy build_image: stage: build image: docker:latest services: - docker:dind script: - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA deploy: stage: deploy script: - ssh userserver docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA docker-compose up -d12. 实战案例12.1 构建 Node.js 应用并 Docker 化应用代码app.jsjavascriptconst express require(express); const app express(); app.get(/, (req, res) res.send(Hello Docker!)); app.listen(3000, () console.log(App running on port 3000));DockerfiledockerfileFROM node:14-alpine WORKDIR /app COPY package*.json ./ RUN npm install --production COPY . . EXPOSE 3000 CMD [node, app.js]构建并运行bashdocker build -t mynodeapp . docker run -d -p 3000:3000 mynodeapp12.2 使用 Docker Compose 部署微服务假设有一个由前端React、后端Node.js、数据库MongoDB组成的应用。yamlversion: 3.8 services: backend: build: ./backend ports: - 5000:5000 environment: - MONGO_URLmongodb://db:27017/app depends_on: - db frontend: build: ./frontend ports: - 3000:3000 depends_on: - backend db: image: mongo:4.4 volumes: - mongo_data:/data/db volumes: mongo_data:12.3 使用 Swarm 部署高可用应用bash# 初始化 Swarm docker swarm init # 部署服务3 个副本 docker service create --name myapp --replicas 3 -p 80:80 myapp:latest # 查看服务状态 docker service ps myapp13. 常见问题与故障排查13.1 容器退出码0正常退出。1应用错误。125Docker 启动失败如未指定命令。126容器内命令无法执行权限问题。127命令未找到。137容器被强制终止如 OOM 杀进程。139段错误。143容器收到 SIGTERM 正常退出。13.2 网络故障容器无法访问外网检查宿主机 IP 转发是否开启net.ipv4.ip_forward1或 DNS 配置。端口映射不生效检查服务是否监听容器内的正确地址如127.0.0.1应改为0.0.0.0。容器间通信失败确认是否在同一网络或自定义网络是否启用。13.3 磁盘空间清理清理未使用的镜像docker image prune -a清理未使用的容器docker container prune清理卷docker volume prune清理网络docker network prune一键清理docker system prune -a --volumes13.4 日志管理Docker 默认将容器的 stdout/stderr 记录到 json-file 驱动日志文件可能占满磁盘。可配置日志轮转bashdocker run --log-opt max-size10m --log-opt max-file3 nginx或在 Docker daemon 全局配置json{ log-driver: json-file, log-opts: { max-size: 10m, max-file: 3 } }14. 总结与进阶学习路径通过本文的学习您应该掌握了 Docker 的核心概念、常用命令、镜像构建、数据管理、网络配置、编排工具Compose、Swarm以及一些安全和高级话题。但要真正精通 Docker还需要在实践中不断积累。进阶学习建议深入学习容器原理研究命名空间、cgroups、联合文件系统的实现。掌握 Docker 源码参与社区贡献。学习 Kubernetes作为容器编排的事实标准。熟悉云原生生态如 Prometheus、Envoy、Istio、Knative 等。DevOps 实践将 Docker 集成到 CI/CD 流水线实现自动化部署。安全加固研究容器安全的更多细节如镜像签名、运行时安全监控。希望本文能成为您 Docker 学习之路上的得力助手如果觉得有用不妨收藏并分享给更多朋友。附录常用命令速查表命令说明docker pull image拉取镜像docker images列出镜像docker rmi image删除镜像docker run image运行容器docker ps列出运行中的容器docker ps -a列出所有容器docker stop container停止容器docker start container启动容器docker rm container删除容器docker exec -it container bash进入容器docker logs container查看日志docker build -t tag .构建镜像docker-compose up -d启动 Compose 服务docker-compose down停止 Compose 服务docker service ls列出 Swarm 服务docker stack deploy -c file stack部署 Stackdocker system prune -a清理所有无用资源