写在前面

本文是我在实习过程中接触到Docker后根据常用的指令和gpt的输出内容整理撰写的学习笔记。

gpt prompt:
我在学习docker并准备写一篇学习博客。请你帮我整理:

  1. 什么是docker;
  2. 下载并安装的流程;
  3. 在windows和linux上使用的区别;
  4. 在本地运行和在docker中运行的区别;
  5. 从确认当前系统中是否有安装docker开始,一直到保存requirement.txt、写dokerfile怎么写、build以及build的作用、run以及run的作用、确认是否成功在docker中运行、停止、删除,的所有常用指令,以及使用portainer.io管理docker
  6. 以及其他你认为重要的、值得放进学习博客的内容。

目录

写在前面

1.什么是Docker

2.安装Docker

2.1.Windows 和 Linux 上使用 Docker 的区别

2.2.Windows

2.3.Linux

3.把python项目放进Docker中运行

3.1.项目结构

3.2.Build

3.3.Run

Docker Compose

3.4.查看

3.5.何时需要 rebuild vs 只需 rerun

4.常用Docker指令

4.1.基础信息

4.2.镜像相关

4.3.容器相关

4.4.端口映射

4.5.目录挂载

4.6.环境变量

4.7.数据卷 volume

4.8.网络 network

4.9.清理命令

5.使用 Portainer.io 图形化管理 Docker


1.什么是Docker

Docker官网链接

Docker 是一个用于构建、打包、运行和分发应用的容器化平台。简单来说,它可以把一个应用及其运行环境,例如 Python 版本、第三方库、系统依赖、启动命令等,一起打包成一个相对独立的运行单元。这样应用就不再强依赖“我电脑上刚好配置好了这个环境”,而是可以在不同机器上尽量以一致的方式运行。

Docker Engine 是 Docker 的核心组件。官方文档将它描述为一种开源容器化技术,采用客户端—服务端架构,主要包括长期运行的 Docker daemon,也就是 dockerd,用于和 daemon 通信的 API,以及命令行客户端 docker。Docker daemon 负责创建和管理镜像、容器、网络、卷等对象。

理解 Docker,先理解几个核心概念:

  • 镜像 image:可以理解为“应用运行环境的模板”。镜像通常包含操作系统基础层、语言运行时、依赖库、项目代码、启动命令等。镜像本身是静态的、只读的。
  • 容器 container:可以理解为“镜像运行起来之后的实例”。同一个镜像可以启动多个容器,就像同一个类可以创建多个对象。
  • Dockerfile:用于描述如何构建镜像的文本文件。Docker 会读取 Dockerfile 中的一系列指令来自动构建镜像。官方文档说明,Dockerfile 是一个文本文件,里面包含用户原本可以在命令行中手动执行、用于组装镜像的命令;常见指令包括 FROMWORKDIRCOPYRUNCMDENTRYPOINTEXPOSEENV 等。
  • 仓库 registry:用于存储和分发镜像。Docker Hub 是公开镜像仓库,并且 Docker 默认会从 Docker Hub 查找镜像。执行 docker pulldocker run 时,如果本地没有对应镜像,Docker 会从配置的 registry 拉取镜像。

说人话:当用Flask、FastAPI、Django封装完了一个应用并想向内网同事提供API接口时,使用命令:uvicorn api_server:app --host 0.0.0.0 --port 8000,可以将你的服务暴露在内网中并让内网同事通过访问“https://你的内网ip:8000/api路由”获取你的服务,但是这需要你的电脑不停止运行程序、不关机。当你将你的服务(程序)部署到Docker上后,它就会在服务器上不停运行,可以7/24通过访问“https://服务器ip:端口/api路由”来获取服务。并且其他同事不需要在他们的电脑上安装你的环境,因为Docker全部都镜像构建好了。Docker 解决的核心问题就是:把应用和环境一起打包,使运行环境尽量标准化、可复制、可迁移。Dockerfile 用来构建 image,image 用来启动 container,container 才是真正运行应用的地方。

2.安装Docker

一般公司都会在服务器上安装好Docker。

2.1.Windows 和 Linux 上使用 Docker 的区别

最主要的是架构差异:

特性 Linux Windows
底层 Docker直接运行在Linux内核上 Docker运行在虚拟机(Hyper-V)或WSL2中
运行方式 原生容器 需要轻量级VM
性能 接近原生性能 有额外开销(约5-15%)

具体来说:

特性 Linux Windows
支持镜像类型 Linux容器 Linux容器 + Windows容器
权限管理 用户组(docker组) 管理员权限
文件系统 直接挂载,性能好 需要额外配置,较慢
网络性能 原生,接近无损耗 有NAT转换,略慢
存储位置 /var/lib/docker 虚拟硬盘文件
路径格式 /path/to/file C:\path\to\file

在 Docker 挂载目录时,Windows 和 Linux 的路径写法不同。

Linux:

docker run -v /home/thomas/project:/app my-image

Windows PowerShell:

docker run -v ${PWD}:/app my-image

Git Bash 或 WSL:

docker run -v $(pwd):/app my-image

在 Windows 上使用 Docker Desktop + WSL 2 时,建议把项目文件放在 WSL 的 Linux 文件系统中,例如:

/home/username/project

而不是频繁在:

/mnt/c/Users/...

中进行大量文件读写。这样通常能减少 Windows 与 Linux 文件系统互操作带来的性能问题。

综上,Linux是Docker的"主场"。

2.2.Windows

推荐方式:Docker Desktop + WSL 2

在 Windows 上学习 Docker,最推荐的方式是安装 Docker Desktop,并使用 WSL 2 后端。Docker 官方文档说明,Docker Desktop for Windows 当前支持 WSL 2 和 Hyper-V 等后端,其中 WSL 2 后端是多数用户常用方式。WSL 2 是微软提供的完整 Linux 内核环境,Docker Desktop 使用 WSL 2 后,用户可以在 Windows 中更方便地运行 Linux 容器。

安装前可以先检查 WSL:

wsl --version

若安装,会返回类似:

WSL 版本: 2.1.5.0
内核版本: 5.15.146.1-2
WSLg 版本: 1.0.60
MSRDC 版本: 1.2.5105
Direct3D 版本: 1.611.1-81528511
DXCore 版本: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows 版本: 10.0.26200.8457

如果没有安装 WSL,可以用管理员 PowerShell 执行:

wsl --install

如果已经安装但版本较旧,可以更新:

wsl --update

Docker 官方 Windows 安装文档也给出了这些 WSL 检查和更新方式。

普通交互式安装流程如下:

  1. 下载 Docker Desktop for Windows 安装包。
  2. 双击 Docker Desktop Installer.exe
  3. 安装过程中选择使用 WSL 2 后端。
  4. 安装完成后启动 Docker Desktop。
  5. 首次启动时接受 Docker Desktop Subscription Service Agreement。
  6. 打开 PowerShell、CMD 或 Windows Terminal,执行:
docker --version
docker run hello-world

2.3.Linux

Linux 上一般安装 Docker Engine。这里以 Ubuntu 为例(我没自己安装过,内容为gpt生成)。

建议安装前先移除发行版提供的非官方或冲突包,例如 docker.iodocker-composepodman-dockercontainerdrunc 等。如果提示有些包不存在,是正常的。

sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-compose-v2 docker-doc podman-docker containerd runc | cut -f1)

然后配置 Docker 官方 apt 仓库:

sudo apt update 
sudo apt install ca-certificates curl 

sudo install -m 0755 -d /etc/apt/keyrings 

sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o etc/apt/keyrings/docker.asc 

sudo chmod a+r /etc/apt/keyrings/docker.asc 

sudo tee /etc/apt/sources.list.d/docker.sources <<EOF 
Types: deb 
URIs: https://download.docker.com/linux/ubuntu 
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") 
Components: stable 
Architectures: $(dpkg --print-architecture) 
Signed-By: /etc/apt/keyrings/docker.asc 
EOF 

sudo apt update

安装 Docker Engine 和 Compose 插件,Docker 官方 Ubuntu 安装文档中的最新版本安装命令就是安装 docker-cedocker-ce-clicontainerd.iodocker-buildx-plugindocker-compose-plugin

sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

然后检查 Docker 服务

sudo systemctl status docker

如果没有启动:

sudo systemctl start docker

设置开机自启:

sudo systemctl enable docker

验证安装:

sudo docker run hello-world

Linux 上免 sudo 使用 Docker:默认情况下,Linux 上经常需要使用 sudo docker ...。如果希望普通用户直接运行 Docker,可以把当前用户加入 docker 用户组:

sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker

然后测试:

docker run hello-world

需要注意:Docker 官方文档明确提醒,docker 用户组会授予接近 root 级别的权限,因此不要随便把不可信用户加入该组。

3.把python项目放进Docker中运行

3.1.项目结构

假设一个简单的项目结构:

my_docker_demo/ 
    ├── main.py 
    ├── requirements.txt 
    ├── Dockerfile 
    └── .dockerignore

注意:文件名必须是 Dockerfile,默认情况下没有后缀,不是 Dockerfile.txt,也不是 dokerfile

requirements.txt可以手动写,也可以使用命令“pip freeze > requirements.txt”导出当前使用的环境中的所有包。

Dockerfile的内容可以是:

# 1. 选择一个轻量级的基础镜像,把x换成任一需要的版本(3.9、3.10......)
FROM python:3.x-slim

# 2. 在容器内创建工作目录
# 设置容器内工作目录。后续命令默认在 /app 下执行。Dockerfile 官方文档建议显式设置 WORKDIR,避免在未知目录中操作。
WORKDIR /app

# 3. 复制依赖文件并安装
COPY requirements.txt .
# 在构建镜像时安装 Python 依赖
RUN pip install --no-cache-dir -r requirements.txt

# 4. 复制项目代码到工作目录
COPY . .
# 这里故意先复制 requirements.txt,安装依赖,再复制完整项目。这样做是为了利用 Docker 构建缓存:当代码变了但依赖没变时,依赖安装层可以复用,构建速度更快。Docker 官方文档也强调,合理使用 build cache 可以跳过不必要的重复构建步骤。

# 5. 声明容器运行时监听的端口
EXPOSE 5000

# 6. 定义容器启动时执行的命令
CMD ["python", "app.py"]
# CMD ["uvicorn", "api_server:app", "--host", "0.0.0.0", "--port", "8000"]
# 一个 Dockerfile 中可以有多个 CMD,但只有最后一个生效。

这个文件告诉 Docker 如何一步步构建出一个包含你应用运行环境的“盒子”(镜像)。

.dockerignore 用于排除不需要发送给 Docker build 的文件。Docker 官方文档说明,构建上下文可以通过 .dockerignore 排除不必要文件;Docker 还支持 ** 这样的通配写法。

.dockerignore 示例:

.venv
__pycache__
*.pyc
.git
.gitignore
.env
.idea
.vscode
dist
build

3.2.Build

写好 Dockerfile 后,在文件所在目录执行构建命令:

docker build -t my-app:v1 .
  • -t my-app:v1 给镜像起个名字和版本号,t:tag。
  • 最后的 . 表示使用当前目录下的 Dockerfile,表示当前目录会作为 build context 发送给 Docker。如果项目里有大文件、虚拟环境、缓存文件,不排除会导致构建变慢,镜像上下文变大,所以这时候就需要.dockerignore

构建完成后查看镜像:

docker images

或者:

docker image ls

你应该能看到:

REPOSITORY        TAG       IMAGE ID       CREATED        SIZE
my-fastapi-app    latest    xxxxxxxx       ...            ...

镜像构建完成,就可以基于它来运行容器了。

如果 Dockerfile 不叫默认的 Dockerfile,可以用:

docker build -f Dockerfile.dev -t my-app:dev .

3.3.Run

使用 docker run 命令,最核心的是通过 -p 参数做端口映射,把容器内的端口暴露给宿主机。

docker run -d -p 5000:5000 --name my-app-container my-app:v1
  • -d:detached,后台运行。
  • -p 5000:5000:将宿主机的 5000 端口映射到容器的 5000 端口。之后你就可以通过 http://你的服务器IP:5000 来访问服务了。也就是访问宿主机的 5000 端口,会转发到容器内部的 5000 端口。
    • 暴露的5000端口(后者)可以与同事的其他项目重复,但是宿主机的5000端口(前者和ip后访问的端口)不能重复。
  • --name:给容器命名,方便管理。
  • --my-app:使用的镜像。

Docker Compose

当项目只有一个容器时,docker run 还可以接受。但如果项目包括后端、数据库如MySQL、缓存如Redis、Nginx 等多个服务,手写多条 docker run 会很麻烦。

  • Nginx (读作 "engine x") 是一个高性能的 Web 服务器反向代理服务器

Docker Compose 用一个 YAML 文件描述多容器应用。Docker 官方文档说明,Compose 用于定义和运行多容器应用,可以在一个 YAML 配置文件中管理服务、网络和卷,然后用一个命令创建和启动整套服务(定义和运行多个容器)。以下是一个示例的compose.yaml文件:

version: '3.8'
services:
  web:  # 你的应用
    build: .  # 使用当前目录的Dockerfile构建
    container_name: my-app-contaianer
    ports:
      - "5000:5000"
    depends_on:
      - db
  db:  # 数据库
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: example
    volumes:
      - db_data:/var/lib/mysql  # 数据持久化

volumes:
  db_data:

启动:

docker compose up

后台启动:

docker compose up -d

停止:

docker compose down

重新构建并启动:

docker compose up -d --build

查看日志:

docker compose logs -f

3.4.查看

确认应用是否真的运行在 Docker 中。

可以查看容器状态:

docker ps

如果看到容器状态是 Up,说明容器正在运行。

也可以查看容器日志

docker logs my-app-container

如果看到 Uvicorn 启动日志,说明服务进程已经在容器中启动。

或者访问接口

curl http://localhost:8000/health

返回:

{"status":"ok"}

说明宿主机可以通过端口映射访问容器内服务。

也可以进入容器检查环境

docker exec -it fastapi-demo /bin/sh

进入后执行:

python --version
pip list
ls /app

如果能看到容器内的 Python、依赖包和项目代码,就说明应用确实在容器环境里。

3.5.何时需要 rebuild vs 只需 rerun

核心原则:

修改内容 是否需要重新 Build 是否需要重新 Run
代码文件 (.py) ✅ 需要 ✅ 需要
依赖文件 (requirements.txt) ✅ 需要 ✅ 需要
Dockerfile ✅ 需要 ✅ 需要
静态文件 (HTML/CSS/JS) ✅ 需要 ✅ 需要
配置文件 (.env) ❌ 看情况 ✅ 需要
数据库内容 (.db) ❌ 不需要 ✅ 只需 Restart

详细说明:

1. 需要重新 Build + Run

修改内容 原因 操作
Python 代码 (*.py) 代码在镜像里 docker build -t container .
docker run ...
依赖包 (requirements.txt) 需要重新安装 docker build -t container .
docker run ...
Dockerfile 构建指令变了 docker build -t container .
docker run ...
HTML/静态文件 被打包进镜像 docker build -t container .
docker run ...

具体操作:

# 1. 停止并删除旧容器
docker stop intent-app
docker rm intent-app

# 2. 重新构建镜像(包含新代码)
docker build -t container .

# 3. 重新运行容器
docker run -d \
  --name intent-app \
  -p 5000:5000 \
  -v $(pwd)/test.db:/app/test.db \
  container

2. 只需要重新 Run(不需要 Build)

这些内容通过挂载 (volume) 方式加载,修改后只需重启或重新创建容器:

修改内容 原因 操作
数据库内容 (*.db) 文件挂载在宿主机 docker restart app
或 docker stop/rm/run
挂载的配置文件 (-v .env:/app/.env) 通过 -v 挂载 docker restart app
日志文件 挂载在宿主机 docker restart app
数据目录 挂载在宿主机 docker restart app

 3. 特殊情况:.env 文件

.env 文件的处理方式决定了需要什么操作:

.env 使用方式 修改 .env 后需要
COPY .env .env (Dockerfile中) 🔨 重新 Build + Run
--env-file .env (docker run参数) 🔄 重新 Run(不用 Build)
-v $(pwd)/.env:/app/.env (卷挂载) 🔄 只需 Restart

4.常用Docker指令

4.1.基础信息

docker --version
docker version
docker info

4.2.镜像相关

docker images
docker image ls

docker pull nginx
docker pull python:3.12-slim

docker build -t my-app .
docker build -t my-app:1.0 .

docker rmi my-app
docker image rm my-app

docker image inspect my-app

4.3.容器相关

docker run hello-world

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

docker ps
docker ps -a

docker stop my-nginx
docker start my-nginx
docker restart my-nginx

docker rm my-nginx
docker rm -f my-nginx

docker logs my-nginx
docker logs -f my-nginx

docker exec -it my-nginx /bin/sh

4.4.端口映射

docker run -p 8080:80 nginx

表示:

宿主机 8080 端口 -> 容器 80 端口

访问:

http://localhost:8080

4.5.目录挂载

docker run -v $(pwd):/app my-app

Windows PowerShell:

docker run -v ${PWD}:/app my-app

常用于开发阶段,让容器直接读取宿主机当前目录代码。

4.6.环境变量

docker run -e APP_ENV=dev my-app

多个环境变量:

docker run -e APP_ENV=dev -e DEBUG=true my-app

4.7.数据卷 volume

创建 volume:

docker volume create mydata

查看 volume:

docker volume ls

使用 volume:

docker run -v mydata:/data my-app

删除 volume:

docker volume rm mydata

4.8.网络 network

查看网络:

docker network ls

创建网络:

docker network create my-net

运行容器并加入网络:

docker run -d --name app --network my-net my-app

删除网络:

docker network rm my-net

4.9.清理命令

删除停止的容器:

docker container prune

删除未使用镜像:

docker image prune

删除未使用 volume:

docker volume prune

删除未使用网络:

docker network prune

谨慎清理所有未使用资源:

docker system prune

连未使用 volume 一起清理:

docker system prune -a --volumes

这个命令很危险,可能删除大量镜像、缓存和数据卷,初学者不要随便执行。

5.使用 Portainer.io 图形化管理 Docker

Portainer 是一个图形化容器管理工具,可以通过浏览器管理 Docker 容器、镜像、卷、网络、Compose stack 等。

进入 Portainer 后,常用功能包括:

  • 查看当前所有容器。
  • 启动、停止、重启、删除容器。
  • 查看容器日志。
  • 进入容器 console。
  • 查看本地镜像。
  • 删除无用镜像。
  • 管理 volume。
  • 管理 network。
  • 用 Stacks 部署 Docker Compose 项目。

这不是一个必须项,如有需要,公司也会提供地址和管理员账户和密码。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐