Docker 的使用

Docker

练习环境:https://www.docker.com/play-with-docker/
官方入门文档: https://docs.docker.com/get-started/overview/
学习资料:https://yeasy.gitbook.io/docker_practice/

想要从零开始学习 Docker 可以直接看上面👆这些资料,下面只整理一些基本的常用命令

前言

  • Docker 是一个开源的应用容器引擎。
  • Docker 是一种容器技术,解决软件跨环境迁移的问题,Docker 容器与虚拟机类似,但是原理不同,容器是将操作系统层虚拟化,而虚拟机是硬件虚拟化

三个基本概念:

安装与配置

镜像加速

代理配置

1
2
3
4
5
6
$ sudo mkdir -p /etc/systemd/system/docker.service.d
$ vim /etc/systemd/system/docker.service.d/http-proxy.conf

[Service]
Environment="HTTP_PROXY=http://proxy.example.com:80"
Environment="HTTPS_PROXY=https://proxy.example.com:443"

基本命令

镜像相关命令

1
2
3
4
$ docker images           # 查看现有镜像
$ docker search redis # 搜索镜像(例如redis)
$ docker pull redis:5.0 # 拉取镜像, 不指定镜像仓库地址则从docker.io获取镜像, 不指定tag则默认是:latest
$ docker rmi cefde848bd49 # 删除镜像(可以指定镜像ID或镜像名称, 镜像ID取前几位能区分开就行)

容器相关命令

1
2
# 例如下面这个命令:
$ docker run --name=c1 -idp 8000:80 -v /var/www/html:/web ubuntu:20.04
  • 基于 ubuntu:20.04 镜像以守护进程方式启动一个容器,并保持 STDIN 打开,将该容器命名为 c1,把容器内部 80 端口映射到本地 8000 端口,并将本地的 /var/www/html 目录映射到容器内部 /web 目录
  • 镜像名后面可指定启动容器后需要执行的命令,不加的话则是默认调用容器在 buildDockerfileCMD 命令指定的
1
2
3
4
5
6
7
# 查看当前运行中的容器
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7406d13e9fe2 ubuntu:20.04 "bash" 19 seconds ago Up 18 seconds 0.0.0.0:8000->80/tcp, :::8000->80/tcp c1

# 进入c1容器
$ docker exec -it c1 /bin/bash
flag 作用
-i 标准输入保持打开(交互式运行容器)
-t 分配一个pseudo-tty(伪终端)
-d 分离模式,也就是在后台启动容器
--name 指定容器名称
-v 宿主机目录(文件):容器内目录(文件) 将宿主机的目录挂载到容器中
-p 宿主机端口号:容器端口号 将容器端口映射到宿主机中
-P 自动将 Dockerfile 中使用 EXPOSE 命令暴露的端口随机映射出来
--rm 当容器退出时自动删除
-e 指定容器内部的环境变量
--network 指定容器使用的网络

更多的flags参考官方文档

1
2
3
4
5
6
$ docker ps                    # 查看正在运行的容器
$ docker ps -a # 查看所有容器
$ docker stop c2 # 停止容器(根据CONTAINER ID或NAMES指定)
$ docker rm c1 # 删除容器(可使用容器ID或容器名称)
$ docker rm -f # 强制删除容器(自动停止并删除)
$ docker rm `docker ps -aq` # 删除所有容器

数据卷操作

📌 数据卷目录挂载的区别是什么?

  • Named volumes
    • 数据卷存放位置由 Docker 统一管理
    • 在初始化时使用容器内容填充空卷
  • Bind mounts
    • 目录由用户自行指定
    • 初始化时不会使用容器内容填充空目录
1
2
3
4
5
6
$ docker volume create vol-demo  # 创建一个名为 vol-demo 的数据卷
$ docker volume ls # 查看所有的数据卷
$ docker volume inspect vol-demo # 查看 vol-demo 数据卷的信息
$ docker volume rm vol-demo # 删除 vol-demo 数据卷
$ docker volume prune # 删除无主数据
$ docker run -d -P --name web --mount source=vol-demo,target=/web nginx # 挂载数据卷
  • 当容器目录和数据卷目录绑定后,两边的修改会立即同步
  • 一个数据卷可以被多个容器同时挂载
  • 一个容器也可以被挂载多个数据卷
  • 容器删除后,数据卷仍然存在

--mount-v

  • -v 前面已经提到了,可以将本地目录挂载到容器当中
    • -v 宿主机目录:容器内目录
  • --mount 相比 -v 来说功能更多,可以更加精准的控制挂载的内容
    • 例如挂载类型、读写权限等
1
2
3
4
# 通过mount将宿主机目录挂载到容器,可通过添加,read-only限制只读
--mount type=bind,source=/var/www/html,target=/web,read-only
# 也可通过mount挂载卷
--mount type=colume,src=vol-demo,dst=/usr/local/data

查看信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ docker system df     # 查看镜像、容器、数据卷所占用空间
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 11 3 7.909GB 5.718GB (72%)
Containers 3 0 264.4MB 264.4MB (100%)
Local Volumes 0 0 0B 0B
Build Cache 286 0 3.56GB 3.56GB

$ docker diff 550 # 查看容器存储层的改动内容
C /etc
A /etc/todos
A /etc/todos/todo.db

$ docker inspect 550 # 获取容器/镜像的元数据
...

$ docker container logs 550 # 获取容器的输出信息
Using sqlite database at /etc/todos/todo.db
Listening on port 3000

Dockerfile

  • 使用 Dockerfile 文件来定制镜像
  • Dockerfile 中的每一个指令都会建立一层,shell 命令尽量写在一行中,用 && 串联,时刻注意这是在构建每一层,而不是 shell 脚本
  • 注意每一层构建的最后一定要清理掉无关文件
1
2
3
docker build -t 镜像名 <上下文路径> [-f <dockerfile path>]

$ docker build -t test-image .

Dockerfile指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# FROM 用来指定基础镜像,必须为第一条指令
FROM ImageName
# RUN 指令用来执行命令行命令,与直接在命令行中输入的命令一样
RUN command
# 复制文件到镜像
COPY [--chown=<user>:<group>] <源路径> <目标路径>
# CMD 用于指定默认容器主进程的启动命令
CMD <命令>
CMD [ "program", "arg1", "arg2" ]

# 用于设置环境变量,容器运行时依旧存在
ENV <key> <value>
# 用于设置环境变量,容器运行时不会存在,定义的默认值可使用--build-arg来覆盖,要使用时需要在各个阶段指定
ARG <key>[=<value>]
# 定义匿名卷
VOLUMNE <路径>
# 声明容器运行时提供服务的端口,在执行docker run -P时会随机映射EXPOSE的端口
EXPOSE <端口1> [<端口2>...]
# 指定工作目录
WORKDIR <工作目录路径>
# 指定当前用户
USER <用户名>[:<用户组>]
# 指定 RUN、ENTRYPOINT、CMD指令的shell,默认是 /bin/sh -c
SHELL ["executable", "parameters"]

更多内容查看:

Docker-Compose

学习资料 👉 https://docs.docker.com/compose/gettingstarted/

安装完成后能正常执行 docker compose version 就 OK:

1
2
$ docker compose version
Docker Compose version v2.20.2

放一个 docker/getting-started 中的例子:

  • 创建 compose.yaml 配置文件:
    • 目前的默认路径是工作目录的 compose.yamlcompose.yml
    • 仍支持早期版本的 docker-compose.yamldocker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos

mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos

volumes:
todo-mysql-data:

启动:

1
$ docker compose up -d

停止并销毁容器和网络:

1
$ docker compose down

复杂的需求就直接查文档 + GPT 吧😅

完整的 compose.yaml 配置说明 👉 https://docs.docker.com/compose/compose-file/03-compose-file/