Docker学习教程
目录
一、Docker 基础入门
1.1 什么是 Docker?
Docker 是一种容器技术,可以将系统的所有文件封装成一个镜像(Image),镜像跑起来作为容器(Container)。
核心优势:
- 把环境和应用打包在一起,解决部署时环境不一致的问题
- 一台机器可以运行多个容器,每个容器都有独立的操作系统环境
- 快速部署多个相同的实例
- 一次构建,到处运行
1.2 Docker 核心概念
| 概念 | 说明 |
|---|---|
| 镜像 (Image) | 只读模板,包含运行应用所需的一切 |
| 容器 (Container) | 镜像的运行实例,可看作一个独立的系统 |
| Dockerfile | 构建镜像的脚本文件 |
| Docker Hub | 官方镜像仓库,可以 pull/push 镜像 |
1.3 安装 Docker
- Windows/Mac:下载安装 Docker Desktop
- Linux:使用包管理器安装
验证安装:
docker --version
1.4 Docker 基本命令
镜像操作
# 搜索镜像
docker search nginx
# 拉取镜像
docker pull nginx:latest
# 查看本地镜像
docker images
# 删除镜像
docker rmi image_name
容器操作
# 运行容器
docker run -d --name my-nginx -p 80:80 nginx:latest
# 查看运行中的容器
docker ps
# 查看所有容器(包括已停止)
docker ps -a
# 停止容器
docker stop container_name
# 启动已停止的容器
docker start container_name
# 删除容器
docker rm container_name
# 进入容器
docker exec -it container_id /bin/sh
# 查看容器日志
docker logs container_id
# 查看容器详情
docker inspect container_id
1.5 端口映射
# -p 宿主机端口:容器端口
docker run -d -p 3000:80 nginx:latest
访问 http://localhost:3000 即可访问容器内的 80 端口服务。
1.6 数据卷(Volume)
数据卷用于持久化数据,解决容器删除后数据丢失的问题。
# -v 宿主机目录:容器目录
docker run -d -v /host/path:/container/path nginx:latest
# 只读挂载
docker run -d -v /host/path:/container/path:ro nginx:latest
为什么需要数据卷?
- 容器删除后,容器内的数据会丢失
- 通过数据卷,数据保存在宿主机上
- 新容器可以挂载同一个数据卷,继续使用数据
1.7 环境变量
# -e KEY=VALUE
docker run -d -e MYSQL_ROOT_PASSWORD=123456 mysql:latest
二、Dockerfile 详解
2.1 Dockerfile 是什么?
Dockerfile 是一个文本文件,包含构建镜像的所有指令。通过 docker build 命令,可以根据 Dockerfile 自动构建镜像。
2.2 Dockerfile 指令
| 指令 | 说明 | 示例 |
|---|---|---|
| FROM | 指定基础镜像 | FROM node:18 |
| WORKDIR | 设置工作目录 | WORKDIR /app |
| COPY | 复制文件到容器 | COPY . . |
| ADD | 复制文件(可自动解压 tar) | ADD ./app.tar.gz /app |
| RUN | 构建时执行命令 | RUN npm install |
| EXPOSE | 声明容器暴露的端口 | EXPOSE 3000 |
| CMD | 容器启动时执行的命令 | CMD ["node", "main.js"] |
| ENTRYPOINT | 容器启动入口(不可覆盖) | ENTRYPOINT ["node"] |
| ENV | 设置环境变量 | ENV NODE_ENV=production |
| ARG | 构建时的参数 | ARG VERSION=1.0 |
| VOLUME | 声明数据卷挂载点 | VOLUME ["/data"] |
2.3 示例:第一个 Dockerfile
FROM node:latest
WORKDIR /app
COPY . .
RUN npm config set registry https://registry.npmmirror.com/
RUN npm install -g http-server
EXPOSE 8080
CMD ["http-server", "-p", "8080"]
构建镜像:
docker build -t my-app:v1 .
运行容器:
docker run -d -p 8888:8080 my-app:v1
2.4 构建上下文
docker build 命令会将当前目录(构建上下文)的所有文件发送给 Docker Daemon。
# . 就是构建上下文的目录
docker build -t name:tag .
2.5 .dockerignore 文件
类似于 .gitignore,用于排除不需要发送给 Docker Daemon 的文件:
*.md
!README.md
node_modules/
.git/
.DS_Store
.vscode/
.env
好处:
- 加快构建速度
- 减小镜像体积
2.6 CMD vs ENTRYPOINT
| 特性 | CMD | ENTRYPOINT |
|---|---|---|
| 可被覆盖 | 是(docker run 传参数会覆盖) | 否 |
| 用途 | 定义默认命令 | 定义固定入口 |
组合使用(推荐):
ENTRYPOINT ["echo", "Hello"]
CMD ["World"]
- 不传参数:执行
echo Hello World - 传参数
docker run image 666:执行echo Hello 666
2.7 COPY vs ADD
| 特性 | COPY | ADD |
|---|---|---|
| 复制文件 | ✓ | ✓ |
| 解压 tar.gz | ✗ | ✓ |
| 下载 URL | ✗ | ✓ |
建议: 一般情况下使用 COPY,只有需要自动解压时才用 ADD。
2.8 VOLUME 指令
在 Dockerfile 中声明数据卷挂载点:
VOLUME ["/data"]
即使 docker run 时没有指定 -v,Docker 也会自动创建一个临时目录挂载上去,保证数据不丢失。
三、Dockerfile 最佳实践
3.1 技巧一:使用 Alpine 镜像
Alpine 是一个极简的 Linux 发行版,镜像体积非常小。
# 体积约 1.45G
FROM node:18
# 体积约 550M
FROM node:18-alpine3.14
建议: 生产环境优先使用 Alpine 镜像。
3.2 技巧二:多阶段构建(Multi-stage Build)
将构建阶段和运行阶段分离,最终镜像只包含运行时需要的文件。
# 构建阶段
FROM node:18-alpine3.14 as build-stage
WORKDIR /app
COPY package.json .
RUN npm config set registry https://registry.npmmirror.com/
RUN npm install
COPY . .
RUN npm run build
# 生产阶段
FROM node:18-alpine3.14 as production-stage
COPY --from=build-stage /app/dist /app
COPY --from=build-stage /app/package.json /app/package.json
WORKDIR /app
RUN npm config set registry https://registry.npmmirror.com/
RUN npm install --production
EXPOSE 3000
CMD ["node", "/app/main.js"]
优势:
- 最终镜像不包含源码和开发依赖
- 镜像体积大幅减小
3.3 技巧三:利用缓存优化构建
Docker 会缓存镜像层,只有变化的层才会重新构建。
正确写法:
# 先复制 package.json,安装依赖(变化少,可缓存)
COPY package.json .
RUN npm install
# 再复制其他文件(变化多)
COPY . .
RUN npm run build
错误写法:
# 这样任何文件变化都会触发 npm install
COPY . .
RUN npm install
3.4 技巧四:ARG 和 ENV
# ARG:构建时的参数,通过 --build-arg 传入
ARG VERSION=1.0
# ENV:运行时的环境变量
ENV NODE_ENV=production
ENV VERSION=${VERSION}
使用:
docker build --build-arg VERSION=2.0 -t my-app .
3.5 完整的生产级 Dockerfile 示例
# 构建阶段
FROM node:18-alpine3.14 as build-stage
WORKDIR /app
# 利用缓存:先复制依赖文件
COPY package.json package-lock.json ./
RUN npm config set registry https://registry.npmmirror.com/
RUN npm ci
# 再复制源码
COPY . .
RUN npm run build
# 生产阶段
FROM node:18-alpine3.14 as production-stage
WORKDIR /app
# 复制构建产物
COPY --from=build-stage /app/dist ./dist
COPY --from=build-stage /app/package.json ./
# 只安装生产依赖
RUN npm ci --production
EXPOSE 3000
CMD ["node", "dist/main.js"]
四、Docker 实现原理
4.1 三大核心技术
Docker 容器的实现依赖于 Linux 内核的三大机制:
| 技术 | 作用 |
|---|---|
| Namespace | 资源隔离 |
| Control Group (cgroup) | 资源限制 |
| UnionFS | 分层存储 |
4.2 Namespace(命名空间)
实现容器内资源的隔离,让容器看起来像一个独立的系统。
| Namespace 类型 | 说明 |
|---|---|
| PID | 进程 ID 隔离 |
| IPC | 进程间通信隔离 |
| Mount | 文件系统挂载隔离 |
| Network | 网络隔离 |
| User | 用户和用户组隔离 |
| UTS | 主机名和域名隔离 |
4.3 Control Group(控制组)
限制容器可以使用的资源:
- CPU 使用量
- 内存大小
- 磁盘 I/O
- 网络带宽
作用: 防止一个容器占用过多资源,影响其他容器。
4.4 UnionFS(联合文件系统)
实现镜像的分层存储。
特点:
- 每一条 Dockerfile 指令生成一层镜像
- 镜像层是只读的,不可修改
- 多个镜像可以共享相同的底层镜像层
- 容器运行时会添加一个可写层
优势:
- 大幅节省磁盘空间
- 快速分发镜像
4.5 镜像分层示意
┌─────────────────────────────────┐
│ 可写层(容器层) │ ← 容器运行时的数据
├─────────────────────────────────┤
│ CMD ["node", "main.js"] │ ← 第 N 层
├─────────────────────────────────┤
│ RUN npm install │ ← 第 2 层
├─────────────────────────────────┤
│ COPY . . │ ← 第 1 层
├─────────────────────────────────┤
│ WORKDIR /app │ ← 第 0 层
├─────────────────────────────────┤
│ node:18-alpine3.14 │ ← 基础镜像(共享)
└─────────────────────────────────┘
五、CI/CD 流程中的 Docker
5.1 标准流程
开发 → 提交代码 → CI 构建镜像 → Push 到 Registry → CD 拉取镜像 → docker run 部署
5.2 常用命令
# 构建镜像
docker build -t my-app:v1 .
# 登录 Docker Hub
docker login
# 给镜像打 tag
docker tag my-app:v1 username/my-app:v1
# 推送到 Docker Hub
docker push username/my-app:v1
# 从服务器拉取并运行
docker pull username/my-app:v1
docker run -d -p 3000:3000 username/my-app:v1
六、常用命令速查表
镜像命令
| 命令 | 说明 |
|---|---|
docker build -t name:tag . | 构建镜像 |
docker images | 查看本地镜像 |
docker pull name:tag | 拉取镜像 |
docker push name:tag | 推送镜像 |
docker rmi image_id | 删除镜像 |
docker tag image name:tag | 给镜像打标签 |
容器命令
| 命令 | 说明 |
|---|---|
docker run -d -p 80:80 image | 运行容器(后台) |
docker ps | 查看运行中的容器 |
docker ps -a | 查看所有容器 |
docker stop container | 停止容器 |
docker start container | 启动容器 |
docker rm container | 删除容器 |
docker exec -it container /bin/sh | 进入容器 |
docker logs container | 查看日志 |
docker inspect container | 查看容器详情 |
数据卷命令
| 命令 | 说明 |
|---|---|
docker volume create name | 创建数据卷 |
docker volume ls | 查看数据卷列表 |
docker volume rm name | 删除数据卷 |
七、实战:部署 Node.js 应用
7.1 项目结构
my-nest-app/
├── src/
├── package.json
├── package-lock.json
├── Dockerfile
└── .dockerignore
7.2 .dockerignore
*.md
node_modules/
.git/
.DS_Store
.vscode/
.env
7.3 Dockerfile
FROM node:18-alpine3.14 as build-stage
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm config set registry https://registry.npmmirror.com/
RUN npm ci
COPY . .
RUN npm run build
FROM node:18-alpine3.14 as production-stage
WORKDIR /app
COPY --from=build-stage /app/dist ./dist
COPY --from=build-stage /app/package.json ./
RUN npm config set registry https://registry.npmmirror.com/
RUN npm ci --production
EXPOSE 3000
CMD ["node", "dist/main.js"]
7.4 构建和运行
# 构建镜像
docker build -t my-nest-app:v1 .
# 运行容器
docker run -d -p 3000:3000 --name my-app my-nest-app:v1
访问 http://localhost:3000 即可看到应用。
总结
- Docker 核心流程:Dockerfile → docker build → 镜像 → docker run → 容器
- 数据持久化:通过 Volume 挂载保证数据不丢失
- 镜像优化:Alpine 镜像 + 多阶段构建 + 合理利用缓存
- 实现原理:Namespace(隔离)+ Control Group(限制)+ UnionFS(分层存储)
掌握这些知识,你就可以高效地使用 Docker 部署和管理应用了!
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐
所有评论(0)