Docker学习

Docker是什么

Docker 是一套把应用连同运行环境一起打包、并在任何机器上几乎一致运行的容器技术。

docker

主要解决三类问题:

  1. 环境一致:利用容器技术,减少本地和真实机器运行环境不一致的问题
  2. 交付标准化:发布物从「一堆文件 + 安装步骤」变成「一个镜像 + 一条启动命令」
  3. 隔离与密度:多个docker容器能跑在同一台物理机上,彼此进程级隔离,相比虚拟机更轻量级

Docker容器与虚拟机的区别

Docker容器

Docker容器之间共用同一个系统内核

docker1

虚拟机

每个虚拟机包含完整的操作系统内核

docker2

Docker是如何实现容器化的

Docker利用了Linux内核的两大原生功能 实现容器化:

  • Cgroups:限制和隔离进程的资源使用,为每个容器设置内存、cpu等资源使用上限,确保一个容器的资源消耗不会影响其他容器和宿主机
  • Namespaces:隔离进程的资源视图,使得容器只能看到自己的文件目录、网络资源而看不到宿主机的,让容器看起来还是一个进程

镜像(Image)

镜像是一份用来创造容器的配置文件,通过一个镜像可以创建多个容器,里面通常包括:

  • 应用程序(编译产物或脚本)
  • 依赖(系统库、运行时如 Node、JRE)
  • 元数据(启动命令、环境变量默认值、暴露端口说明等)

Docker Hub

Docker的官方镜像仓库是Docker Hub,存储官方和其他开发者分享的镜像

镜像相关的常用命令

  • docker build:根据 Dockerfile 构建镜像
  • docker pull:从仓库 拉取镜像
  • docker images:列出本地镜像

利用Dive分析镜像

我们可以通过Dive分析镜像组成,以一个node镜像(koa)为例,整个镜像组成包括:

  • 基础系统层(用户态文件系统、基础系统库):FROM blobs、apt-get
  • 业务代码相关(COPY):业务文件被打进镜像的层
  • 应用依赖层:RUN npm install # buildkit,也就是node_modules里的依赖

dive

通过这里也可以看到,Docker 镜像不是一个单文件,而是由多层(layer)叠加出来的,详细见:layer概念


容器(Container)

容器可以理解成最小型的一个操作系统环境,可以对各种服务以及应用容器化,是镜像的运行实例

容器相关常用命令

  • docker run
  • docker ps
  • docker container
  • docker rm

后台运行

让容器在后台运行,不影响当前命令行

1
docker run -d

端口映射

容器的网络和宿主机的网络是隔离的,默认情况下并不能从宿主机直接访问到docker的内部网络,所以要把容器内的端口和宿主机的端口做一个映射

1
docker run -p xxxx:xxxx

端口映射

挂载卷

绑定挂载
-v:把宿主机和容器的文件目录进行绑定,常用于数据的持久化缓存
因为删除容器时,容器内的数据会被永久删除掉, 如果使用挂载卷,容器对应的数据也会被保存到宿主机对应的文件目录里

1
docker run -v /Users/you/data:/app/data my-image

挂载卷

命名卷

1
docker volume create

(第一次创建时会把容器里的文件复制过来)

设置环境变量

1
docker run -e

容器改名

1
docker run --name

控制台进入容器进行交互

1
docker run -it

容器停止时自动删除容器

1
docker run --rm

容器停止后的重启策略

–restart always:停止就立马重启

1
docker run --restart always nginx:alpine

unless-stop:手动停止不会强制重启

1
docker run --restart unless-stopped nginx:alpine

测试容器

1
docker exec

Dockerfile

在使用 docker 部署自己应用时,往往需要独立构建镜像。

docker 使用 Dockerfile 作为配置文件构建镜像,简单看一个 nginx静态资源服务器的 dockerfile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# ====== build stage ======
FROM node:20-alpine AS builder

WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile

COPY . .
RUN yarn build

# ====== runtime stage ======
FROM nginx:1.27-alpine

# 拷贝 nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf

# 拷贝前端静态产物
COPY --from=builder /app/build /usr/share/nginx/html

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

FROM

声明这一 stage 的基础镜像,后面的 RUN、COPY 等都基于它的文件系统和环境。

ADD

把构建上下文里的文件/目录(或一个 URL)放进镜像指定路径。

RUN

在构建镜像时执行一条或多条 shell 命令(安装依赖、编译、npm run build 等)。

CMD

指定容器启动时默认执行的命令(主进程)。镜像可以没有 ENTRYPOINT 时,CMD 就是容器入口。

Layer(分层)的概念

Docker 镜像不是一个单文件,而是由多层(layer)叠加出来的

  • 每条 RUN / COPY / ADD 指令通常会产生一层(FROM 是基础层)。
  • 层是只读的,容器启动后会在最上面再加一层可写层(容器层)。
  • 在构建时可以利用缓存,详细可见:Docker构建缓存

对应上面的 Dockerfile,大致可以理解为:

  • FROM node:20-alpine AS builder:构建阶段基础层(Node 运行时 + Alpine 用户态)。
  • COPY package.json yarn.lock ./ + RUN yarn install --frozen-lockfile:依赖清单层 + 依赖安装层
  • COPY . . + RUN yarn build:业务代码层 + 构建产物层(生成前端静态文件)。
  • FROM nginx:1.27-alpine:运行阶段基础层(仅保留 nginx 运行环境)。
  • COPY nginx.conf ... + COPY --from=builder /app/build ...:运行时配置层 + 静态产物层
  • EXPOSE 80CMD ["nginx", "-g", "daemon off;"]:镜像元数据(端口声明与启动命令)

利用dive验证:
dive2


Docker Network

bridge模式

宿主机网络和容器网络隔离,通过bridge去做端口映射

host模式

直接使用宿主机网络的模式

none模式

不联网


Docker Compose

容器编排技术

compose up

compose down


K8s

大规模的容器编排