1. 基本概念

Snipaste_2021-12-29_20-48-44

  • Docker Daemon:运行在 Docker 服务器的后台进程,侦听 Docker API 请求并管理 Docker 对象,例如镜像、容器、网络和挂载卷,守护进程还可以与其他守护进程通信以管理 Docker 服务
  • Docker Client: Docker 客户端是许多 Docker 用户与 Docker 交互的主要方式,当使用 docker run 之类的命令时,客户端会将这些命令发送到 dockerd,从而执行它们,该 docker 命令使用 Docker API,Docker 客户端可以与多个守护进程通信
  • Docker Host:安装 Docker 服务的主机
  • Docker Registries:存储 Docker Image 的地方,Docker Hub 是一个任何人都可以使用的公共仓库,Docker 默认配置为在 Docker Hub 上查找镜像,也可以使用自己的仓库,当使用 docker pull 或 docker run 命令时,所需的镜像将从配置的仓库中查找,当使用 docker push 命令时,镜像会被推送到你配置的仓库中
  • Images:镜像是用于创建 Docker 容器的只读模板,通常,一个镜像基于另一个镜像,并带有一些额外的自定义,可以自己创建镜像,也可以使用公共仓库中发布的镜像,构建镜像需要创建一个 Dockerfile,用于定义创建镜像和运行镜像所需的步骤,Dockerfile 中的每条指令都会在镜像中创建一个层,当更改 Dockerfile 并重建镜像时,只会重建那些已更改的层,与其他虚拟化技术相比,这是使镜像如此轻巧、小巧和快速的部分原因
  • Containers:容器是镜像的可运行实例,可以使用 Docker API 或 CLI 创建、启动、停止、移动或删除容器,可以将容器连接到一个或多个网络,为其附加存储,也可以根据其当前状态创建新镜像,默认情况下,容器与其他容器及其主机相对隔离,可以控制容器的网络、存储或其他底层子系统与其他容器或主机之间的隔离程度,容器由镜像以及创建或启动它时提供给它的任何配置选项定义,当容器被移除时,未存储在持久存储中的对其状态的任何更改都会消失

Docker 用 Go 语言编写,并利用 Linux 内核的几个特性来提供其功能,Docker 使用一种称为 namespaces 的技术来实现资源隔离,运行容器时,Docker 会为该容器创建一组 namespaces, 这些 namespaces 提供了一层资源隔离,容器的每个方面都在单独的 namespaces 中运行,并且对其的访问仅限于该 namespaces

2. 隔离原理

2.1 namespace(资源隔离)

namespace系统调用参数隔离内容
UTSCLONE_NEWUTS主机和域名
IPCCLONE_NEWIPC信号量、消息队列和共享内存
PIDCLONE_NEWPID进程编号
NetworkCLONE_NEWNET网络设备、网络栈、端口等
MountCLONE_NEWNS挂载点(文件系统)
UserCLONE_NEWUSER用户和用户组

2.2 cgroups(资源限制)

  • 资源限制:限制任务使用的资源总额,并在超过这个配额时发出提示
  • 优先级分配:分配 CPU 时间片数量及磁盘 IO 带宽大小、控制任务运行的优先级
  • 资源统计:统计系统资源使用量,如 CPU 使用时长、内存用量等
  • 任务控制:对任务执行挂起、恢复等操作

cgroup 资源控制系统,每种子系统独立地控制一种资源,功能如下:

子系统功能
cpu使用调度程序控制任务对 CPU 的使用
cpuacct(CPU Accounting)自动生成 cgroup 中任务对 CPU 资源使用情况的报告
cpuset为 cgroup 中的任务分配独立的 CPU (多处理器系统时)和内存
devices开启或关闭 cgroup 中任务对设备的访问
freezer挂起或恢复 cgroup 中的任务
memory设定 cgroup 中任务对内存使用量的限定,并生成这些任务对内存资源使用情况的报告
perf_event(Linux CPU性能探测器)使 cgroup 中的任务可以进行统一的性能测试
net_cls(Docker未使用)通过等级识别符标记网络数据包,从而允许 Linux 流量监控程序(TraicController)识别从具体 cgroup 中生成的数据包

3. 安装

# 移除旧版本
yum remove docker*

# 设置 yum 源
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/dockerce/linux/centos/docker-ce.repo

# 找到所有可用 docker 版本列表
yum list docker-ce --showduplicates | sort -r

# 安装最新版本 docker engine
yum install docker-ce docker-ce-cli containerd.io

# 安装指定版本 docker engine
yum install docker-ce-<VERSION_STRING>.x86_64 docker-ce-cli-<VERSION_STRING>.x86_64 containerd.io

# 离线安装
rpm -ivh xxx.rpm
// https://download.docker.com/linux/centos/7/x86_64/stable/Packages/

# 启动服务
systemctl start docker
systemctl enable docker

3.1 镜像加速

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
    "registry-mirrors": ["https://registry.docker-cn.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

3.2 可视化界面-Portainer

# 服务端部署(访问 9000 端口)
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v
/var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce

# agent 端部署
docker run -d -p 9001:9001 --name portainer_agent --restart=always -v
/var/run/docker.sock:/var/run/docker.sock -v /var/lib/docker/volumes:/var/lib/docker/volumes portainer/agent

4. 常用命令

Snipaste_20211229_211353.png

命令作用
attach绑定到运行中容器的标准输入、输出、以及错误流
build从一个 Dockerfile 文件构建镜像
commit把容器的改变提交创建一个新的镜像
cp容器和本地文件系统间复制文件或目录
create创建新容器,但是不启动,需要手动启动
diff检查容器里文件系统结构的更改(A:添加文件或目录 D:文件或者目录删除 C:文件或者目录更改)
events获取服务器的实时事件
exec在运行时的容器内运行命令
export导出容器的文件系统为一个 tar 文件,commit 是直接提交成镜像,export 是导出成文件方便传输
history显示镜像的历史
images列出所有镜像,image ls
import导入 tar 的内容创建一个镜像,再导入进来的镜像直接启动不了容器
info显示系统信息
inspect获取 docker 对象的底层信息
kill杀死一个或多个容器
load从 tar 文件加载镜像
login登录 Docker registry
logout退出 Docker registry
logs获取容器日志,可以看到容器在控制台输出的所有内容
pause暂停一个或多个容器
port列出容器的端口映射
ps列出所有容器
pull从 registry 下载一个 image 或者 repository
push给 registry 推送一个 image 或者 repository
rename重命名一个容器
restart重启一个或者多个容器
rm删除一个或多个容器
rmi删除一个或多个镜像
run创建并启动容器
save把一个或者多个镜像保存为 tar 文件
search去 docker hub 寻找镜像
start启动一个或者多个容器
stats显示容器资源的实时使用状态
stop停止一个或者多个容器
tag给源镜像创建一个新的标签,变成新的镜像
top显示正在运行容器的进程
unpausepause 的反操作
udpate更新一个或多个 docker 容器配置
versionShow the Docker version infomation
container管理容器
image管理镜像
network管理网络
volume管理卷

4.1 docker run

  • -d: 后台运行容器,并返回容器 ID
  • -i: 以交互模式运行容器,通常与 -t 同时使用
  • -P: 随机端口映射,容器内部端口随机映射到主机的端口
  • -p: 指定端口映射,格式为:主机(宿主)端口:容器端口
  • -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用
  • --name="nginx-lb": 为容器指定一个名称
  • --dns 8.8.8.8: 指定容器使用的 DNS 服务器,默认和宿主一致
  • --dns-search example.com: 指定容器 DNS 搜索域名,默认和宿主一致
  • -h "mars": 指定容器的 hostname
  • -e username="ritchie": 设置环境变量
  • --env-file=[]: 从指定文件读入环境变量
  • --cpuset="0-2" or --cpuset="0,1,2": 绑定容器到指定CPU运行
  • -m: 设置容器使用内存最大值;
  • --net="bridge": 指定容器的网络连接类型,支持 bridge/host/none/container 四种类型
  • --link=[]: 添加链接到另一个容器
  • --expose=[]: 开放一个端口或一组端口
  • --restart: 指定重启策略,可以写--restart=awlays 总是故障重启
  • --volume: -v 绑定一个卷,一般格式 主机文件或文件夹:虚拟机文件或文件夹

4.2 docker exec

  • docker exec -it alpine sh

4.3 docker build

  • docker build -t imageName -f DockerfileName

4.4 常见部署案例

4.4.1 部署 Nginx
# 注意: 外部的 /nginx/conf 下面的内容必须存在,否则挂载会覆盖
docker run --name nginx-app \
-v /app/nginx/html:/usr/share/nginx/html:ro \
-v /app/nginx/conf:/etc/nginx
-d nginx
4.4.2 部署 MySQL
# 5.7 版本
docker run -p 3306:3306 --name mysql57-app \
-v /app/mysql/log:/var/log/mysql \
-v /app/mysql/data:/var/lib/mysql \
-v /app/mysql/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=123456 \
-d mysql:5.7

# 8.x 版本,引入了 secure-file-priv 机制,磁盘挂载将没有权限读写 data 数据,所以需要将权限透传,或者 chmod -R 777 /app/mysql/data
# --privileged 特权容器,容器内使用真正的 root 用户
docker run -p 3306:3306 --name mysql8-app \
-v /app/mysql/conf:/etc/mysql/conf.d \
-v /app/mysql/log:/var/log/mysql \
-v /app/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--privileged
4.4.3 部署 Redis
# 提前准备好 redis.conf 文件,创建好相应的文件夹,如:
port 6379
appendonly yes
# 更多配置参照 https://raw.githubusercontent.com/redis/redis/6.0/redis.conf
docker run -p 6379:6379 --name redis \
-v /app/redis/redis.conf:/etc/redis/redis.conf \
-v /app/redis/data:/data \
-d redis:6.2.1-alpine3.13 \
redis-server /etc/redis/redis.conf --appendonly yes
4.4.4 部署 ElasticSearch
# 准备文件和文件夹,并 chmod -R 777 xxx
# 配置文件内容,参照 https://www.elastic.co/guide/en/elasticsearch/reference/7.5/node.name.html 搜索相关配置
docker run --name=elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms300m -Xmx300m" \
-v /app/es/data:/usr/share/elasticsearch/data \
-v /app/es/plugins:/usr/shrae/elasticsearch/plugins \
-v esconfig:/usr/share/elasticsearch/config \
-d elasticsearch:7.12.0
4.4.5 部署 Tomcat
docker run --name tomcat-app -p 8080:8080 \
-v tomcatconf:/usr/local/tomcat/conf \
-v tomcatwebapp:/usr/local/tomcat/webapps \
-d tomcat:jdk8-openjdk-slim-buster
4.4.6 重启策略
  • no: 默认策略,在容器退出时不重启容器
  • on-failure: 在容器非正常退出时(退出状态非0),才会重启容器
  • on-failure:3,在容器非正常退出时重启容器,最多重启3次
  • always: 在容器退出时总是重启容器
  • unless-stopped: 在容器退出时总是重启容器,但是不考虑在 Docker 守护进程启动时就已经停止了的容器

Q.E.D.


盛年不重来,一日难再晨。