“为什么刚刚能运行,现在就不行,为什么刚刚不运行,现在就可以,为什么他的可以跑,我的不能跑,为什么我的可以跑,他的就不行,为什么这台电脑能,那台就不能”

在软件开发中最大的问题之一就是环境不一致。

Docker 就是为了解决这些问题而生的,所以我开始学习Docker,并通过书写教程的方式,来巩固自己学习的记录

准备工作

Docker简介

Docker 是一个开源的应用容器化平台,它允许开发者将应用及其所有依赖打包到一个称为“容器”的标准化单元中,让它可以在任何环境中以相同的方式运行。

核心概念

为了更好地理解 Docker,我们需要掌握三个核心概念:

1. 镜像 (Image):可以理解为容器的“蓝图”或“模板”。它包含了运行应用所需的所有内容——代码、运行时、系统工具、库和设置。镜像是一个只读的静态文件。

2. 容器 (Container):镜像的运行实例。你可以把容器看作是一个轻量级的、独立的执行环境。容器是可写的、可启动、停止和删除的。

3. 仓库 (Registry):存储和分发镜像的地方。Docker Hub 是最流行的公共镜像仓库,你可以在这里找到成千上万的官方和社区镜像。

Docker 与虚拟机的区别

很多人会把 Docker 和虚拟机混淆,但它们的本质完全不同,简单来说,虚拟机虚拟的是硬件,而 Docker 虚拟的是操作系统。因此容器更加轻量、快速和高效。

安装 Docker

在Linux上安装(Centos为例)

安装依赖包

sudo yum install -y yum-utils

添加 Docker 软件源

sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

安装 Docker

sudo yum install docker-ce docker-ce-cli containerd.io

启动 Docker 服务

sudo systemctl start docker
sudo systemctl enable docker

验证安装

docker --version

Docker实践

让我们从最经典的程序开始:

docker run hello-world

这个命令会,检查本地是否有 hello-world 镜像,如果没有则从 Docker Hub 拉取,创建一个容器并运行,输出欢迎信息后容器自动停止

常用基础命令

镜像相关

列出本地镜像

docker images

搜索镜像

docker search nginx

拉取镜像:latest指的是最后一个版本,也就是最新版

docker pull nginx:latest

删除镜像

docker rmi <镜像ID>

构建镜像

docker build -t my-app:v1 .

容器相关命令

运行容器(前台运行)

docker run nginx

运行容器(后台运行)加入参数-d

docker run -d nginx

列出运行中的容器

docker ps

列出所有容器(包括停止的)

docker ps -a

停止容器

docker stop <容器ID>

启动已停止的容器

docker start <容器ID>

进入容器内部

docker exec -it <容器ID> /bin/bash

删除容器

docker rm <容器ID>

查看容器日志

docker logs <容器ID>

查看容器资源占用

docker stats <容器ID>

运行一个真正的 Web 应用示例

让我们运行一个 Nginx Web 服务器:

拉取 Nginx 镜像

docker pull nginx

运行 Nginx 容器,映射端口 80 到宿主机的 8080

docker run -d -p 8080:80 --name my-nginx nginx

验证:在浏览器访问 http://localhost:8080,你应该能看到 Nginx 的欢迎页面

查看容器日志

解释:

- -d:后台运行(detach 模式)

- -p 8080:80:端口映射,将容器的 80 端口映射到宿主机的 8080 端口

- --name my-nginx:为容器指定名称

Volume 的使用

容器被删除后,里面的数据也会丢失。为了持久化数据,我们需要使用卷(Volume):

创建数据卷

docker volume create my-data

运行容器并挂载数据卷

docker run -d -v my-data:/usr/share/nginx/html -p 8080:80 --name nginx-with-data nginx

或者使用绑定挂载(将宿主机目录挂载到容器)

docker run -d -v /path/to/host:/usr/share/nginx/html -p 8080:80 nginx

构建自定义的镜像

Dockerfile 是一个文本文件,包含了构建镜像所需的全部指令。让我们创建一个简单的 Python Web 应用镜像。

首先创建一个项目目录:

mkdir my-python-app
cd my-python-app

创建 app.py:(这个是我ai的,仅仅作为示例)

from flask import Flask

import os

app = Flask(__name__)

@app.route('/')

def hello():

return f'Hello from Docker! Hostname: {os.uname().nodename}'

if name == '__main__':

app.run(host='0.0.0.0', port=5000)

创建 requirements.txt

flask==2.3.2

创建 Dockerfile

# 使用官方 Python 镜像作为基础镜像

FROM python:3.9-slim

# 设置工作目录

WORKDIR /app

# 复制依赖文件并安装

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码

COPY app.py .

# 暴露端口

EXPOSE 5000

# 启动命令

CMD ["python", "app.py"]

构建并运行:

构建镜像

docker build -t my-python-app:v1 .

运行容器并验证

docker run -d -p 5000:5000 --name my-app my-python-app:v1

在浏览器访问 http://localhost:5000

Docker Compose管理多容器应用

当应用由多个服务组成(如 Web 应用 + 数据库)时,Docker Compose 可以让管理变得简单。

创建 docker-compose.yml:(规则)

version: '3.8'

services:

web:

build: .

ports:

- "5000:5000"

environment:

- REDIS_HOST=redis

depends_on:

- redis

volumes:

- ./app.py:/app/app.py

redis:

image: redis:alpine

ports:

- "6379:6379"

volumes:

- redis-data:/data

volumes:

redis-data:

使用 Compose 管理应用:

启动所有服务

docker-compose up -d

查看服务状态

docker-compose ps

查看日志

docker-compose logs web

停止并删除所有服务

docker-compose down

停止并删除所有服务,同时删除数据卷

docker-compose down -v

Docker 最佳实践建议

镜像优化: 使用多阶段构建减小镜像体积

FROM python:3.9-slim AS builder

COPY requirements.txt .

RUN pip install --user -r requirements.txt

FROM python:3.9-slim

COPY --from=builder /root/.local /root/.local

COPY . .

ENV PATH=/root/.local/bin:$PATH

CMD ["python", "app.py"]

Docker 安全配置 Q&A

Q:为什么不要以 root 用户运行容器?

A:容器内 root 权限存在提权风险,攻击者可能借此控制宿主机。应创建专用用户运行应用。

Q:如何在 Dockerfile 中创建非 root 用户?

A:

RUN useradd -m -u 1000 appuser

USER appuser

Q:"使用最新镜像"具体指什么?

A:指定期更新基础镜像版本,及时修复已知漏洞。但生产环境建议锁定精确版本(如 nginx:1.25.3),而非 latest,避免环境不一致。

Q:如何扫描镜像漏洞?

A:使用 docker scan <镜像名> 命令即可扫描已知漏洞。

Q:如何限制容器的 CPU 和内存?

A:运行容器时添加参数:

docker run --memory=512m --cpus=1.5 my-app:v1

dockerignore

类似于 .gitignore,创建一个 .dockerignore 文件排除不需要的文件:

node_modules

*.log

Dockerfile

.dockerignore

日志管理

配置日志驱动

docker run --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 nginx

常见问题排查

端口被占用时:

查看端口占用

netstat -tulpn | grep 8080

lsof -i :8080

停止占用端口的容器

docker stop <容器ID>

磁盘空间不足时

查看 Docker 磁盘使用情况

docker system df

清理未使用的资源

docker system prune -a

清理所有停止的容器、网络、镜像和缓存

docker system prune -a -f

容器无法启动时

查看详细日志

docker logs <容器ID>

进入容器的调试模式

docker run -it --entrypoint /bin/bash <镜像名>

推荐的下一步学习计划与建议

接下来是个人走过的学习路径,推荐按照这个顺序进行学习:

学习 Kubernetes,管理大规模容器集群

探索 CI/CD,将 Docker 集成到持续集成/持续部署流程

了解容器网络,理解 Docker 的网络模式

研究安全最佳实践:构建更加安全的容器化应用