Docker基础
视频连接:戳我哦
1、Docker概述
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,更重要的是容器性能开销极低。
Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版)
- 开源容器引擎
- 操作系统级别的虚拟化技术,进程级别的隔离
- 依赖于linux内核特性:namespace(资源隔离)和Cgroup(资源限制)
- 一个简单的应用打包工具
2、容器 VS 虚拟机
3、Docker组成
- docker client
- docker daemon
- docker image
- docker container
- docker registry
4、Docker安装部署
官方地址:https://docs.docker.com/engine/install/ubuntu/
1、环境规划
服务器配置:
- 建议最小配置:2核CPU、2G内存、20G硬盘
- 最好可以连接外网,方便拉取镜像,不能,提前下载镜像导入节点
软件环境:
软件 | 版本 |
---|---|
Ubuntu | ubuntu-20.04.3-live-server-amd64 |
Docker | 目前最新:20.10.12 |
服务器规划:
主机名 | IP |
---|---|
k8s-master-1 | 192.168.6.31 |
2、操作系统初始化
1. 配置静态IP
在Ubuntu 20.04上,系统使用“predictable network interface names(可预测的网络接口名称)”标识网络接口。
-
识别要配置的以太网接口名称
ip link
-
配置分配静态IP
Netplan配置文件存储在/etc/netplan目录中。 您可能会在此目录中找到一个或多个YAML文件。 文件的名称可能因安装程序而异。 通常,文件名为01-netcfg.yaml,50-cloud-init.yaml或NN_interfaceName.yaml
vim /etc/netplan/00-installer-config.yaml
- :set paste(ubuntu下的vim编辑器粘贴格式可能存在混乱)
# This is the network config written by 'subiquity'
network:
ethernets:
ens32:
dhcp4: false
addresses:
- 192.168.6.31/24
gateway4: 192.168.6.2
nameservers:
addresses: [8.8.8.8, 114.114.114.114]
version: 2
要将静态IP地址分配给ens32接口,请按照以下步骤编辑文件:
- 将DHCP设置为dhcp4: no。
指定静态IP地址。 在addresses:下,您可以添加一个或多个将分配给网络接口的IPv4或IPv6 IP地址。
- 指定网关。
- 在nameservers下,设置以下IP地址: 域名服务器。
- gateway4地址根据自己的自行修改,我这里之前设置的是2(一般是1)
- 保存并应用配置
sudo netplan apply
- 验证更改
ip addr show dev ens32
-
使用开启root远程连接
# 设置root密码 sudo passwd root # 开启远程登录 sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config sudo systemctl restart ssh
-
设置时区
dpkg-reconfigure tzdata # 选择Asia -> 再选择Shanghai -> OK # 或者使用 cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
或者直接使用命令:
timedatectl set-timezone Asia/Shanghai
-
设置时间格式
# 需要修改时间为24小时,可以修改/etc/default/locale,默认没有LC_TIME这个变量,在文件中增加一行: LC_TIME=en_DK.UTF-8 # 重启生效
2. 初始化操作系统
sudo apt-get update
# 禁用swap分区(修改/etc/fstab,注释掉swap那行,持久化生效)
swapoff -a # 临时
sed -ri 's/.*swap.*/#&/' /etc/fstab # 永久
# 主机名规划
hostnamectl set-hostname k8s-master-1
# 同步时间
apt-get install ntpdate -y
ntpdate time.windows.com
# 确保每个机器不会自动suspend(待机/休眠)
sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target
Ubuntu开启swap分区:
修改系统的
/etc/default/grub
文件,修改一下参数(默认为空)GRUB_CMDLINE_LINUX=”cgroup_enable=memory swapaccount=1”
sudo update-grub
命令更新系统- 重启系统
3、安装Docker
官方地址:https://docs.docker.com/engine/install/ubuntu/
1. 卸载旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc
2. 设置存储库
sudo apt-get -y install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
3. 添加Docker官方的GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
4. 使用以下命令设置稳定存储库
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
5. 安装引擎
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
如果要安装特定版本如下:
apt-cache madison docker-ce # 列出版本 sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io # Ubuntu系统安装好像版本号后面需要指定-00 sudo apt-get install docker-ce=20.10.12-00 docker-ce-cli=<VERSION_STRING> containerd.io
6. 验证
docker info
7、配置docker镜像加速
国内从 DockerHub 拉取镜像有时会遇到困难,Docker 官方和国内很多云服务商都提供了国内加速器服务
- 科大镜像:https://docker.mirrors.ustc.edu.cn/
- 网易:https://hub-mirror.c.163.com/
- 阿里云:**https://<你的ID>.mirror.aliyuncs.com**你的ID>
- 七牛云加速器:https://reg-mirror.qiniu.com
阿里云镜像获取地址:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"log-opts": {
"max-size": "100m",
"max-file":"5"
},
"registry-mirrors": [
"https://b9pmyelo.mirror.aliyuncs.com",
"https://3fc19s4g.mirror.aliyuncs.com",
"https://hub-mirror.c.163.com",
"https://registry.aliyuncs.com",
"https://registry.docker-cn.com",
"https://docker.mirrors.ustc.edu.cn"
],
"insecure-registries": ["https://dockerhub.kubekey.local"],
"exec-opts": ["native.cgroupdriver=systemd"],
"data-root": "/data/docker"
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
5、Docker镜像
镜像不是一个单一的文件,而是有多层构成。我们可以通过docker history <imageID/name>
查看镜像中各层内容及大小,每层 对应着Dockerfile中的一条指令。Docker镜像默认存储在/var/lib/docker/<storage-driver>
中。
docker官方镜像仓库 :https://hub.docker.com/explore
- 一个分层存储的文件
- 一个软件的环境
- 一种标准化的交付
- 一个不包含Linux内核而又精简的Linux操作系统
1、Docker镜像和容器的关系
一对多,一个镜像可以创建多个容器
容器其实是在镜像的最上面加了一层读写层,在运行容器里文件改动时, 会先从镜像里将要写的文件复制到容器自己的文件系统中(读写层)。 如果容器删除了,最上面的读写层也就删除了,改动也就丢失了。所以无论多 少个容器共享一个镜像,所做的写操作都是从镜像的文件系统中复制过来操作 的,并不会修改镜像的源文件,这种方式提高磁盘利用率。
若想持久化这些改动,可以通过docker commit 将容器保存成一个新镜像。
2、Docker常用镜像管理命令
指令 | 描述 |
---|---|
ls | 列出镜像 |
build | 构建镜像 |
history | 查看镜像历史 |
inspect | 显示一个或多个镜像详细信息 |
pull | 拉取镜像 |
push | 推送镜像 |
search | 搜索镜像 |
rmi | 移除一个或多个镜像 |
prune | 移除未使用的镜像(没有被标记或被任何容器引用的) |
tag | 创建一个引用源镜像标记目标镜像 |
export | 导出容器文件系统到tar归档文件 |
import | 导入容器文件系统tar归档文件创建镜像 |
save | 保存一个或多个镜像到一个tar归档文件 |
load | 加载镜像来自tar归档或标准输入 |
3、操作实例
-
拉取镜像
busybox:1.28.4
和nginx
docker pull busybox:1.28.4 docker pull nginx
-
导出
nginx
镜像到/opt/images
docker save nginx:latest | gzip > /opt/images/nginx-latest.tar.gz
-
删除镜像
nginx
docker rmi nginx:latest
-
导出
nginx
镜像,文件名为nginx-latest.tar.gz
,位于/opt/images
docker load -i nginx-latest.tar.gz
6、Docker容器
1、docker常见的容器管理命令
指令 | 描述 |
---|---|
ls | 列出容器 |
inspect | 显示一个或多个容器详细信息 |
exec | 在运行的容器中执行命令 |
commit | 创建一个新镜像来自容器 |
cp | 拷贝文件或文件夹 |
logs | 获取一个容器日志 |
port | 列出或指定容器映射端口 |
top | 显示一个容器运行的进程 |
stats | 显示容器资源使用统计 |
stop/start/restart | 停止/启动一个或多个容器 |
rm | 删除一个或多个容器 |
2、创建容器是常用的选项
选项 | 描述 |
---|---|
-i, –interactive | 交互式 |
-t, –tty | 分配一个伪终端 |
-d, –detach | 后台运行 |
-e, –env | 设置环境变量 |
-p, –publish list | 映射容器端口到主机 |
-P, –publish-all | 映射容器所有EXPOSE的端口到宿主机随机端口 |
–name string | 指定容器名称 |
-h, –hostname | 设置容器主机名 |
–ip string | 指定容器ip,只能用于自定义网络 |
–network | 连接容器到一个网络 |
-v, –volume list | 绑定挂载卷 |
–restart string 可选值:[always | on-failure] |
3、资源限制常用选项
选项 | 描述 |
---|---|
-m, –memory | 容器使用的最大内存量 |
–memory-swap | 允许交换到磁盘的内存量 |
–memory-swappiness=<0-100> | 容器使用SWAP分区交换的百分比(0-100,默认为-1) |
–oom-kill-disable | 禁用OOM Killer |
–cpus | 可以使用的CPU数量 |
–cpuset-cpus | 限制容器使用特定的CPU核心,如(0-3, 0,1) |
–cpu-shares | CPU共享(相对权重) |
- cpuset-cpus:多个容器竞争同一CPU的时间片时,才会存在竞争现象
4、Docker资源限制
Docker通过linux的Cgroup 来控制容器使用的资源额度,其中有CPU、内存、磁盘等,基本覆盖了常见的资源配额和使用量控制。
防止某个或一些容器占用大量(例如某些服务被黑),影响其他容器的正常运行,资源限制显得尤为重要。
1. Cgroup介绍
cgroups(Control Groups) 是 linux 内核提供的一种机制(Linux 2.6.24内核开始将Cgroup加入主线), 这种机制可以根据需求把一系列系统任务及其子任务整合(或分隔)到按资源划分等级的不同组内,从而 为系统资源管理提供一个统一的框架。简单说,cgroups 主要用于限制和隔离一组进程对系统资源的使 用,也就是做资源QoS。可控制的资源主要包括CPU、内存、block I/O、网络带宽等等。本质上来说, cgroups 是内核附加在程序上的一系列钩子(hook),通过程序运行时对资源的调度触发相应的钩子以达 到资源追踪和限制的目的。
2. stress介绍
stress是一款压力测试工具,可以用它来对系统CPU,内存,以及磁盘IO生成负载。
apt-get install stress
yum -y install epel-release
yum -y install stress
参数解释:
-? 显示帮助信息
-v 显示版本号
-q 不显示运行信息
-n,--dry-run 显示已经完成的指令执行情况
-t --timeout N 指定运行N秒后停止
--backoff N 等待N微妙后开始运行
-c --cpu 产生n个进程 每个进程都反复不停的计算随机数的平方根
-i --io 产生n个进程 每个进程反复调用sync(),sync()用于将内存上的内容写到硬盘上
-m --vm n 产生n个进程,每个进程不断调用内存分配malloc()和内存释放free()函数
--vm-bytes B 指定malloc时内存的字节数 (默认256MB)
--vm-hang N 指示每个消耗内存的进程在分配到内存后转入休眠状态,与正常的无限分配和释放内存的处理相反,这有利于模拟只有少量内存的机器
-d --hadd n 产生n个执行write和unlink函数的进程
--hadd-bytes B 指定写的字节数,默认是1GB
--hadd-noclean 不要将写入随机ASCII数据的文件Unlink
时间单位可以为秒s,分m,小时h,天d,年y,文件大小单位可以为K,M,G
-
对CPU压测
# 运行两个进程把CPU占满,30s后结束 stress -c 2 -v -t 30m
-
对内存压测
stress -m 3 --vm-bytes 300M
-
对磁盘压测
stress -i 2 -d 4
5、操作实例
-
使用
nginx
镜像创建一个名为web
的容器,并以后台方式运行以及对外暴露服务(8080)docker run -d -p 8080:80 --rm --name web nginx
-
使用
busybox:1.28.4
镜像创建名为busybox
的容器,以交互式运行docker run -it --rm --name busybox busybox:1.28.4 # 指定主机名 docker run -it -h mytest --rm --name busybox busybox:1.28.4
-
内存限制
# 允许容器最多使用100M内存和200M的Swap,并禁用 OOM Killer: docker run -it --rm --name test --memory="100m" --memory-swap="200m" --oom-kill-disable geray/centos:v7-1 bash # 检查 docker inspect test | grep -i memory # 查看内存大小(默认单位:Bytes) cat /sys/fs/cgroup/memory/memory.limit_in_bytes
-
CPU限制
# 允许容器最多使用一个半的CPU: docker run -d --rm --name nginx01 --cpus="1.5" nginx # 允许容器最多使用50%的CPU: docker run -d --rm --name nginx02 --cpus=".5" nginx # 绑定容器到cpu1的核心上,并给定500的权重占比 docker run -itd --rm --name cpu --cpuset-cpus 1 --cpu-shares 500 geray/centos:v7-1 /bin/bash # 检查CPU配置 docker inspect cpu | grep -i cpu
-
压测CPU:创建容器
cpu0
和cpu1
,同时绑定在cpu0上,并压测观察(尽管没有占100%权重,一样可以使用100%)docker run -itd --rm --name cpu0 --cpuset-cpus 0 --cpu-shares 500 geray/centos:v7-1 bash docker run -itd --rm --name cpu1 --cpuset-cpus 0 --cpu-shares 1000 geray/centos:v7-1 bash # 进入容器安装stress docker exec -it cpu0 bash yum -y install epel-release yum -y install stress # 压测:运行两个进程把CPU占满,30s后结束 stress -c 2 -v -t 30m
-
内存:
docker run -it --rm --name memory1 -m 128m geray/centos:v7-1 # 查看内存大小(默认单位:Bytes) cat /sys/fs/cgroup/memory/memory.limit_in_bytes
如果存在警告:未开启swap分区
ubuntu或其他基于Debian的系统上才会出现的问题,原因是系统默认未开启swap限制;
修改系统的
/etc/default/grub
文件,修改一下参数(默认为空)GRUB_CMDLINE_LINUX=”cgroup_enable=memory swapaccount=1”
sudo update-grub
命令更新系统- 重启系统
-
创建容器
limit0
,只能使用1个CPU核心和128m内存docker run -it --rm --name limit0 --cpuset-cpus 1 -m 128m geray/centos:v7-1 bash
-
使用
mysql:8
镜像练习
docker pull mysql:8
docker run -d --rm --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=12345 mysql:8
docker run -it mysql mysql -h 192.168.6.31 -uroot -p
7、Docker挂载(持久化存储)
- 容器中的数据如何存储?
- web应用的日志如何存储?如何获取错误日志排查故障?
- 每一个容器都会有一个相关的挂载(默认位置:
/var/lib/docker/overlay2/<容器ID>
) - 容器使用overlay读写
1、储存卷概述
操作系统的目录树是由一组挂载点创建而成,这些挂载点描述了如何能构建出一个或多个文件系统。
存储卷是容器目录树上的挂载点,其中一部分主机目录树已经被挂载了。
如果没有存储卷,Docker 用户会受限于Union文件系统,仅提供镜像挂载。
如上图:容器中运行着的一个程序,正写数据到文件中。
第一个文件写入到了根文件系统。操作系统控制根文件系统将改变的部分装入 Union文件系统的顶层。
第二个文件则写入到已经挂载于容器目录树/data 中。改动会通过存储卷直接影响到主机文件系统上。
虽然Union文件系统适用于构建和分享镜像,但对持久化或共享数据而言,并不是理想的方法。存储卷填补了这些用例,并在容器化系统设计中发挥了关键作用。
存储卷特点:
- 一个数据分割和共享的工具
- 与容器无关的范围和生命周期
2、挂载数据到容器
Docker提供三种方式将数据从宿主机挂载到容器中:
- volumes:Docker管理宿主机文件系统的一部分(/var/lib/docker/volumes)。保存数据的最佳方式。
- Bind Mounts:将宿主机上的任意位置的文件或者目录挂载到容器中。
- tmpfs:挂载存储在主机系统的内存中,而不会写入主机的文件系统。如果不希望将数据持久存储在任何位置,可以使用 tmpfs,同时避免写入容器可写层,提高性能。(临时保存到内存中,容器停止
tmpfs
被删除)
Docker数据卷相关命令docker volume --help
3、volume
- Docker管理宿主机文件系统的一部分(默认位置:
/var/lib/docker/volumes
) - 保存数据的最佳方式。
# 管理卷:
docker volume create nginx1
docker volume create nginx2
docker volume ls
docker volume inspect nginx1
# 用卷创建一个容器:
docker pull geray/nginx:v1.17.10
# 容器数据映射到宿主机
docker run -d --rm -p 8080:80 --name=nginx1 --mount src=nginx1,dst=/usr/local/nginx/html geray/nginx:v1.17.10
docker run -d --rm -p 8081:80 --name=nginx2 -v nginx2:/usr/local/nginx/html geray/nginx:v1.17.10
# 清理:
docker stop nginx1 nginx{1,2}
docker rm nginx1 nginx{1,2}
docker volume rm nginx{1,2} # 删除数据卷
小结:
- 如果没有指定卷,自动创建。
- 建议使用–mount,更通用。
- volume只能存放到docker的特定区域(默认位置:
/var/lib/docker/volumes/<volume-name>/_data
) - docker管理宿主机文件系统的一部分
- src数据卷中如果有数据,会将数据映射到容器中,并隐藏容器中原有的数据
- src数据卷中如果没有数据,会将容器中的原有数据映射出来
4、Bind Mounts
- 宿主机任意位置与docker容器映射
- bind mounts不由docker管理
- bind mounts可以将宿主机上的任意位置的文件或者目录挂载到容器中
- volume会将容器中的原有文件映射到宿主机(宿主机原位置是否存在文件?),bind mounts会将宿主机数据映射到容器(隐藏原有容器的源文件)
- 格式:
--mount type=bind,src=源目录,dst=目标目录
# 挂载目录:
docker run -d -it -p 8083:80 --name=nginx3 --mount type=bind,src=/tmp/nginx3,dst=/usr/local/nginx/html geray/nginx:v1.17.10
# /tmp/nginx3必须存在
docker run -d -it -p 8084:80 --name=nginx4 -v /tmp/nginx4:/usr/local/nginx/html geray/nginx:v1.17.10
# 挂载文件
docker run -d -it -p 8085:80 --name=nginx5 -v /tmp/nginx5/index.html:/usr/local/nginx/html/index.html geray/nginx:v1.17.10
docker run -d -it -p 8086:80 --name=nginx6 --mount type=bind,src=/tmp/nginx6/index.html,dst=/usr/local/nginx/html/index.html geray/nginx:v1.17.10
# 验证绑定:
docker inspect <container-name>
# 清理:
docker stop nginx{1..6}
docker rm nginx{1..6}
rm -rf /tmp/nginx{1..6}
小结:
目录:
- 使用mount挂载目录时,src源目录必须存在(否则抛出错误信息)
- 使用
-v
挂载目录时,src源目录不存在会自动创建
文件:
mount
和-v
挂载文件,src源文件必须存在,否则抛出错误信息:bind source path does not exist: <文件路径>.
bind Mount无论src
源位置中是否存在数据,都会隐藏容器中原有数据
5、Volume VS Bind Mounts总结
- 使用
-v
参数挂载时,:
前如果是路径则是bind mounts
方式,否则是volume
方式 - 两种方式挂载时,如果宿主机目录中存在数据,则会覆盖容器中原有的数据
Volume:
- 如果没有指定卷,自动创建。
- 多个运行容器之间共享数据,多个容器可以同时挂载相同的卷。
- volume只能存放到docker的特定区域(默认位置:
/var/lib/docker/volumes/<volume-name>/_data
) - docker管理宿主机文件系统的一部分(当容器停止或被移除时,该卷依然存在;明确删除卷时,卷才会被删除。 )
- src数据卷中如果有数据,会将数据映射到容器中,并隐藏容器中原有的数据
- src数据卷中如果没有数据,会将容器中的原有数据映射出来
- 将容器的数据存储在远程主机或其他存储上(间接)
- 将数据从一台Docker主机迁移到另一台时,先停止容器,然后备份卷的目录(/var/lib/docker/volumes/)
Bind Mounts
-
使用mount挂载目录时,src源目录必须存在(否则抛出错误信息)
-
使用
-v
挂载目录时,src源目录不存在会自动创建 -
mount
和-v
挂载文件,src源文件必须存在,否则抛出错误信息:bind source path does not exist: <文件路径>.
-
bind Mount无论src源位置中是否存在数据,都会隐藏容器中原有数据(错误描述)
6、tmpfs
tmpfs是Linux/Unix系统上的一种基于内存的虚拟文件系统。tmpfs可以使用您的内存或swap分区来存储文件(即它的存储空间在virtual memory 中, VM由real memory和swap组成)。由此可见,tmpfs主要存储暂存的文件。
特点:
- 动态文件系统的大小。
- tmpfs 使用VM建的文件系统,速度当然快。
- 重启后数据丢失。
实际应用中,为应用的特定需求设定此文件系统,可以提升应用读写性能,如将squid 缓存目录放在/tmp, php session 文件放在/tmp, socket文件放在/tmp, 或者使用/tmp作为其它应用的缓存设备
如果Docker位于Linux操作系统上,可以使用tmpfs
mounts。使用tmpfs
挂载创建容器时,容器可以在容器的可写层外创建文件。
与volume和绑定挂载相反,tmpfs
挂载是临时的,并且仅保留在主机内存中。当容器停止后,将tmpfs
删除安装,并且不会保留写在那里的文件。
- tmpfs无法实现容器间共享
- 只有在Linux上运行Docker时才能使用此功能
tmpfs使用(没有src)
- 该
--tmpfs
标志不允许您指定任何可配置选项。 - 该
--tmpfs
标志不能与swarm服务一起使用。你必须使用--mount
。
使用tmpfs挂载的两种方式
--tmpfs
标志--mount
带有type=tmpfs
和destination
选项的 标志
# --mount type=tmpfs方式
docker run -itd --name nginx-tmpfs1 --mount type=tmpfs,dst=/usr/local/nginx/app geray/nginx:v1.17.10
# --tmpfs方式
docker run -itd --name nginx-tmpfs2 --tmpfs /usr/local/nginx/app geray/nginx:v1.17.10
docker stop nginx-tmpfs{1,2}
docker rm nginx-tmpfs{1,2}
指定tmpfs选项:
选项 | 描述 |
---|---|
tmpfs-size | tmpfs的大小以字节为单位。默认无限制。 |
tmpfs-mode | 八进制中tmpfs的文件模式。例如,700 或0770 。默认为1777 或全局可写。 |
# 使用tmpfs挂载,并设置容器不是全局可读
docker run -d -it \
--name tmptest \
--mount type=tmpfs,dst=/usr/local/nginx/app,tmpfs-mode=1770 \
geray/nginx:v1.17.10
7、操作实例
-
创建名为
tomcat
的volume数据卷docker volume create tomcat
-
使用
geray/tomcat9:latest
镜像创建容器-
容器名:tomcat
-
将容器的端口映射到宿主机上的8080端口
docker pull geray/tomcat9:latest docker inspect geray/tomcat9:latest | grep -A2 -i ExposedPorts docker run -d --name tomcat -p 8080:8080 geray/tomcat9:latest
-
-
使用
geray/tomcat9:latest
镜像创建tomcat1
容器,对外暴露端口8081- 使用上面创建的
tomcat
卷挂载镜像的日志目录 - 使用
volume
方式挂载容器中的配置文件到tomcat-conf
数据卷 - 使用
bind mounts
方式挂载tomcat的项目路径到/tmp/tomcat/webapps
- 通过宿主机修改index.html并访问
mkdir -p /tmp/tomcat/webapps docker run -d \ --name tomcat1 -p 8081:8080 \ --mount type=volume,src=tomcat,dst=/usr/local/tomcat/logs \ -v tomcat-conf:/usr/local/tomcat/conf \ --mount type=bind,src=/tmp/tomcat/webapps,dst=/usr/local/tomcat/webapps \ geray/tomcat9:latest
- 使用上面创建的
-
清理环境
for i in $(docker ps -a | awk '{print $1}');do docker stop $i && docker rm $i;done docker volume prune rm -rf /tmp/tomcat
8、Docker网络
# 查看是否开启IPv4转发
sysctl net.ipv4.ip_forward
# 开启IPv4网络转发功能
sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g' /etc/sysctl.conf
sysctl -p /etc/sysctl.conf
# 重启网络服务(CentOS)
systemctl restart network
Docker的4种网络模型:
-
bridge:使用
--net=bridge
指定(默认)。默认网络,Docker启动后创建一个docker0网桥,默认创建的容器也是添加到这个网桥中。
docker run -itd --net=bridge --name=net1 geray/nginx:v1.17.10
-
host:使用
--net=host
指定。容器不会获得一个独立的network namespace,而是与宿主机共用一个。这就意味着容器不会有自己的网卡信息(端口映射也会不生效),而是使用宿主机的。容器除了网络,其他都是隔离的。
docker run -it --net=host --name=net2 geray/nginx:v1.17.10 bash
-
none:使用
--net=none
指定。获取独立的network namespace,但不为容器进行任何网络配置,需要我们手动配置。
docker run -it --net=none --name=net3 geray/nginx:v1.17.10 bash
挂在这个网络下的容器除了 lo,没有其他任何网卡(感兴趣的可以借助pipework配置IP)
-
container:使用
--net=container:<NAME_or_ID>
指定。与指定的容器使用同一个network namespace,具有同样的网络配置信息,两个容器除了网络,其他都还是隔离的。
docker run -it --net=container:net1 --name=net4 geray/nginx:v1.17.10 bash
-
自定义网络
与默认的bridge原理一样,但自定义网络具备内部DNS发现,可以通过容器名容器之间网络通信。
Docker网络相关命令docker network --help
# 清理环境
docker stop net{1..4}
docker rm net{1..4}
1、操作实例
-
创建一个名为mysql的网络,并使用bridge模式
docker network create mysql --driver=bridge
-
使用MySQL官方镜像及说明创建MySQL容器并测试连接(并进行挂载测试)
# 创建mysql容器,并使用docker的mysql网络 docker run -d --name mysql \ -h test \ --net=mysql \ -p 3306:3306 \ -v /tmp/mysql:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=12345 \ mysql:8 # 创建一个同网络的容器并连接 docker run -it --name test --rm mysql:8 mysql -h172.23.0.1 -uroot -p
-
删除上面创建的网络和容器
docker stop mysql test docker rm mysql test docker network prune docker volume prune
9、Dockerfile
1、构建镜像的原则
- 小巧安全、适当复用
尽量选择小的基础镜像,避免安装不必要的软件包、减少镜像层数、最小化容器权限
Linux操作系统的基础镜像:
镜像名称 | 大小 | 使用场景 |
---|---|---|
busybox | 1.15MB | 临时测试用 |
alpine | 4.41MB | 主要用于测试,也可用于生产环境 |
centos | 200MB | 主要用于生产环境,支持CentOS/Red |
ubuntu | 81.1MB | 主要用于生产环境,常用于人工智能计算和企业应用 |
debian | 101MB | 主要用于生产环境 |
2、Dockerfile命令说明
指令 | 描述 |
---|---|
FROM | 基准镜像 |
MAINTAINER(已弃用) | 镜像维护者姓名和邮箱地址 |
LABEL | 设置标签比MAINTAINER 更强大 |
RUN | 构建镜像时运行的shell命令 |
COPY | 拷贝数据到镜像 |
ENV | 设置环境变量 |
USER | 设置用户名或UID |
EXPOSE | 声明容器运行的服务端口 |
HEALTHCHECK | 容器中服务健康检查 |
VOLUME | 声明挂载路径 |
WORKDIR | 设置工作目录 |
ENTRYPOINT | 设置默认命令,运行容器时执行,多个指令时最后一个生效 |
CMD | 设置ENTRYPOINT 参数,运行容器时执行,多个CMD指令时最后一个生效 |
3、CentOS基础镜像构建实例
更多功能的CentOS基础镜像
locale -a
不支持中文语言
FROM centos:7
MAINTAINER "Geray <1690014753@qq.com>"
#LABEL geray=1690014753@qq.com
RUN yum -y install kde-l10n-Chinese && \
yum -y reinstall glibc-common && \
yum clean all && \
rm -rf /var/cache/yum/* && \
localedef -c -f UTF-8 -i zh_CN zh_CN.utf8 && \
echo "LC_ALL=\"zh_CN.UTF-8\"" > /etc/locale.conf
#env
ENV TZ "Asia/Shanghai"
#ENV LANG en_US.UTF-8
ENV LANG zh_CN.UTF-8
- kde-l10n-Chinese:中文语言包
yum -y reinstall glibc-common
更新包(防止镜像不能成功加载语言包)localedef -c -f UTF-8 -i zh_CN zh_CN.utf8
设置系统语言
构建并导出镜像练习
docker build -t <image-name>:<label> .
# 注意后面的. 表示当前路径(Dockerfile的目录里)
# 如果Dockerfile不在当前目录下,可以使用-f 指定
# 构建
docker build -t centos7:latest .
# 导出
docker save centos7:latest | gzip > cnetos7-latest.tar.gz
# 删除镜像并根据导出的文件导入镜像
docker rmi centos7:latest
docker load -i cnetos7-latest.tar.gz
3、镜像优化
-
尽量避免不必要的软件包
降低复杂性并减少依赖;比如:开发调试所需的软件包
-
尽量减少镜层数
便于维护并减小镜像大小,比如软件包的安装命令放到同一个
RUN
中,避免将缓存提交到镜像中yum install 和 yum clean 放在同一个 RUN 指令中
-
选择最小的基础镜像
-
最小权限原则运行应用程序
-
利用缓存加速构建
docker build 按照 Dockerfile 中指令的顺序逐个执行,并把每个指令的构建结果缓存起来,这样下次构建的时候就可以进行复用;尽量把很少变化的指令放到前面,而经常变化的指令(比如 COPY 和 CMD)放到后面。
4、.dockerignore
使用
作用:
- 防止无用文件被复制到镜像中
方式1:指定需要被复制的文件
cat .dockerignore
*
! file1
! /opt/file2
- "*"表示的意思是把所有目录或文件都拒绝了
- "!"表示被接受的路径或文件
方式2:指定不需要被复制的文件
cat .dockerignore
mailer-base.d
fmailer-logging.d
fmailer-live.df
5、多阶段构建(multi-stage builds)
1. 构建原理
多阶段构建通过在Dockerfile中使用多个 FROM指令实现。每一条 FROM 指令都是一个构建阶段,多个 FROM指令就是多阶段构建。
多阶段构建的意义在于:在构建的过程中,可以选择性的将前面阶段中必要的文件复制到后面的阶段中,并抛弃不需要的文件。这样,最后的镜像中只保留需要的文件(减少镜像大小)。
2. 实例
- hello.go
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println("多阶段镜像构建测试")
fmt.Printf("Hello, %s!\n", runtime.GOARCH)
}
- Dockerfile
FROM golang:1.13.5
WORKDIR /go/src/github.com/helloworld/
# RUN go get -d -v golang.org/x/net/html # 官方实例中使用的代理
# go get命令——一键获取代码、编译并安装
# -d 只下载不安装
# -v 显示执行的命令
RUN go get -d -v github.com/go-sql-driver/mysql
COPY hello.go .
# 编译go
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o hello .
# 镜像构建
FROM alpine:latest
LABEL geray=1690014753@qq.com \
author=Geray \
TIME=2022.9.13
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/helloworld/hello .
CMD ["./hello"]
当CGO_ENABLED=1, 进行编译时, 会将文件中引用libc的库(比如常用的net包),以动态链接的方式生成目标文件。 当CGO_ENABLED=0, 进行编译时, 则会把在目标文件中未定义的符号(外部函数)一起链接到可执行文件中。
GOOS=linux 编译成linux可执行的二进制文件。
- 构建
docker build -t geray/hello:v1 .
3. AS 阶段命名
FROM golang:1.13.5 as builder
WORKDIR /go/src/github.com/helloworld/
# RUN go get -d -v golang.org/x/net/html # 官方实例中使用的代理
# go get命令——一键获取代码、编译并安装
# -d 只下载不安装
# -v 显示执行的命令
RUN go get -d -v github.com/go-sql-driver/mysql
COPY hello.go .
# 编译go
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o hello .
# 镜像构建
FROM alpine:latest
LABEL geray=1690014753@qq.com \
author=Geray \
TIME=2022.9.13
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/helloworld/hello .
CMD ["./hello"]
4. –target 指定阶段构建
可以使用 –target构建指定阶段的镜像,该阶段镜像构建完即停止。
构建上面两个阶段中的第一个:builder
docker build --target builder -t geray/hello:target_builder .
5. COPY –from 从其他镜像复制文件
可以使用COPY –from指令从其他镜像(如前面阶段构建的镜像,本地镜像,Docker Hub上的镜像)
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=hello:target_builder /go/src/github.com/helloworld/hello .
CMD ["./hello"]
构建
docker build -t geray/hello:builder-from .
6、构建不同架构的镜像
我们来简单看下以下的常见的四大主流芯片架构:
ARM和X86架构最显著的差别是使用的指令集(复杂指令集)不同,RiSC-V架构与MIPS架构是一种采取精简指令集(RISC)的处理器架构。
1. 跨 CPU 架构编译程序的不同方法
方式1 - 直接在目标硬件上编译
如果我们可以访问目标架构硬件,同时该操作系统支持运行构建所需的各种工具,那么就可以直接在硬件上编译应用程序。
方式2 - 模拟目标硬件
QEMU是一套由法布里斯·贝拉(Fabrice Bellard)所编写的以GPL许可证分发源码的模拟处理器软件,在GNU/Linux平台上使用广泛。
Bochs,PearPC等与其类似,但不具备其许多特性,比如高速度及跨平台的特性,通过KQEMU这个闭源的加速器,QEMU能模拟至接近真实电脑的速度。
方式3 - 模拟目标硬件的用户空间
在 Linux 系统上,QEMU 有另外一种操作模式,可以通过用户模式模拟器来运行非本地架构的二进制程序。
该模式下,QEMU 会跳过方法 2 中描述的对整个目标系统硬件的模拟,取而代之的是通过 binfmt_misc 在 Linux 内核注册一个二进制格式处理程序,
将陌生二进制代码拦截并转换后再执行,同时将系统调用按需从目标系统转换成当前系统。
最终对于用户来说,他们会发现可以在本机运行这些异构二进制程序。
通过 QEMU 的用户态模式,我们可以创建轻量级的虚拟机(chroot 或容器),然后在虚拟机系统中编译程序,和本地编译一样简单轻松。
跨平台构建 Docker 镜像用的就是这个方法。
方法4 - 使用交叉编译器
一种在嵌入式系统社区标准的做法:交叉编译。
交叉编译器是专门为在给定的系统平台上运行而设计的编译器,但是可以编译出另一个系统平台的可执行文件。
例如,amd64 架构的 Linux 系统上的 C++ 交叉编译器可以编译出运行在 aarch64(64-bit ARM) 架构的嵌入式设备上的可执行文件。安卓设备的 APP 基本上都是通过这种方法来编译的。
从性能角度来看,该方法与方法 1 没什么区别,因为不需要模拟器的参与,几乎没有性能损耗。
但交叉编译不具有通用性,它的复杂度取决于程序使用的语言。如果使用 Golang 的话,那就超级简单。
在云原生容器时代,我们讨论构建时不仅包括构建单个可执行文件,还包括构建容器镜像。
而且构建容器镜像比上面说的方法更复杂,再加上 Docker 本身的复杂性,这是一个很复杂的问题。
为了能够更方便的构建多架构 Docker 镜像,我们可以使用最近发布的 Docker 扩展:buildx。
buildx 是下一代标准 docker build 命令的前端,既我们熟悉的用于构建 Docker 镜像的命令。
通过借助 BuildKit ,buildx 扩展了表中 docker build 命令的功能,成为 Docker 构建系统的新后端。
docker manifest create合并多架构镜像推送到私有仓库
docker pull nginx:latest --platform linux/arm64
docker tag nginx:latest repos.cloud.cmft/ruoyi/nginx:latest-arm64
docker push repos.cloud.cmft/ruoyi/nginx:latest-arm64
docker pull nginx:latest --platform linux/amd64
docker tag nginx:latest repos.cloud.cmft/ruoyi/nginx:latest-amd64
docker push repos.cloud.cmft/ruoyi/nginx:latest-amd64
# 需要先push tag后的镜像到私有仓库,遇到证书问题可以使用insecure进行忽略
docker images | grep nginx
docker manifest create repos.cloud.cmft/ruoyi/nginx:latest repos.cloud.cmft/ruoyi/nginx:latest-arm64 repos.cloud.cmft/ruoyi/nginx:latest-amd64
docker manifest push repos.cloud.cmft/ruoyi/nginx:latest --insecure
参考链接:https://www.zhaowenyu.com/docker-doc/reference/dockercmd/dockercmd-manifest-create.html
2. 启用buildx插件
Docker 版本不低于 19.03
开启buildx 功能
默认情况下,buildx已经在安装包里面了
在 ~/.docker/config.json增加,是家目录的client端的配置不是/etc下的服务端配置
"experimental": "enabled"
即可永久开启buildx命令
为了良好的支持性,如果是centos版本需要升级内核到5.12.9才能正常使用
centos7内核升级
下载插件
mkdir -pv ~/.docker/cli-plugins/
wget -O ~/.docker/cli-plugins/docker-buildx \
https://github.com/docker/buildx/releases/download/v0.5.1/buildx-v0.5.1.linux-amd64
chmod a+x ~/.docker/cli-plugins/docker-buildx
启用插件
cat ~/.docker/config.json
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "Z2VyYXk6R2VyYXkmTGkxMTM="
},
"registry.cn-hangzhou.aliyuncs.com": {
"auth": "MTczMzk4NzIxNjU6R2VyYXlAMjAyMg=="
}
}
}
{
"experimental": "enabled"
}
systemctl restart docker
docker buildx version
linux系统需要设置binfmt_misc,否则没有缺少很多架构,其他系统默认已开启
# 创建实例
docker buildx create --name mybuilder --driver docker-container
# 使用实例
docker buildx use mybuilder
# 查看已有实例
docker buildx ls
# 安装模拟器(用于多平台镜像构建)
docker run --rm --privileged tonistiigi/binfmt:latest --install all
# 或者使用
docker run -d --name binfmt --rm --privileged docker/binfmt:66f9012c56a8316f9244ffd7622d7c21c1f6f28d
# 查看支持其他架构的镜像的运行环境
docker buildx inspect --bootstrap
# 或者
ls /proc/sys/fs/binfmt_misc/qemu-*
3. 构建支持多个架构的镜像
这是一个多阶段构建 Dockerfile,使用 Go 编译器来构建应用,并将构建好的二进制文件拷贝到 alpine 镜像中。
buildx 构建一个支持 arm、arm64 和 amd64 多架构的 Docker 镜像。
FROM golang:1.13.5
LABEL maintainer xcbeyond
WORKDIR /app
COPY hello.go /app
RUN go build -o hello /app/hello.go
CMD ["./hello"]
构建镜像并上传
# 登陆dockerhub
docker login -ugeray
# 构建镜像并上传到镜像仓库
docker buildx build -t geray/hello:buildx-v1 --platform=linux/arm,linux/arm64,linux/amd64 --push .
4. 模拟arm架构系统
https://blog.csdn.net/xiang_freedom/article/details/92724299
docker开启manifest功能
~/.docker/config.json
中添加参数
{
"auth": {},
"experimental": "enabled"
}
/etc/docker/daemon.json
中添加参数
{
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com",
"https://docker.mirrors.ustc.edu.cn",
"https://3fc19s4g.mirror.aliyuncs.com"
],
"experimental": true
}
重启docker服务
systemctl daemon-reload
systemctl restart docker
# 检查是否开启
docker manifest
#查看docker是否开启experimental功能
docker version
拉取镜像测试
# 下载arm镜像
docker pull arm64v8/ubuntu
docker pull arm32v7/ubuntu:18.04
docker run -it -v /usr/bin/qemu-aarch64-static:/usr/bin/qemu-aarch64-static --name arm_test --rm arm64v8/ubuntu bash
docker run -it -v /usr/bin/qemu-aarch64-static:/usr/bin/qemu-aarch64-static --name arm_test --rm arm32v7/ubuntu:18.04 bash
5. 获取不同架构的镜像并测试脚本
# 查看镜像架构信息
docker manifest inspect --insecure geray/hello:buildx-v1
# 拉取指定架构的镜像
docker pull --platform=arm64 geray/hello:buildx-v1
# 打包后解压出hello脚本
docker save -o hello.tar geray/hello:buildx-v1
# 解压tar文件
tar xf hello.tar
# 查看manifest.json可以看到具体哪个layer是最新的。
# 找其中一个layer再解压
cd <层>
tar xf layer.tar
# 模拟arm架构服务运行脚本
docker run -it --name arm_test --rm arm64v8/ubuntu bash
docker cp hello arm_test:/
docker exec -it arm_test bash /hello
7、manifest构建多架构镜像到私有仓库
1.命令操作
- 操作过程
首先,推送每个架构对应的镜像: bash复制代码 docker push your-image:tag-amd64 docker push your-image:tag-arm64 然后,创建镜像清单: bash复制代码 docker manifest create --insecure your-image:tag \ --amend your-image:tag-amd64 \ --amend your-image:tag-arm64 推送清单到 Docker Hub: bash复制代码 docker manifest push --insecure your-image:tag 这会创建一个多架构镜像标签,Docker 会根据主机的架构自动选择适当的镜像版本。
- 例如
```
拉取镜像并使用架构版本后缀构建tag,并推送至镜像仓库(同一镜像仓库的同一个镜像,使用不同架构后缀区分)
docker pull birdhk/fluid-csi:v0.9.1-16937652 –platform linux/arm64 docker tag birdhk/fluid-csi:v0.9.1-16937652 repos-yltest-mgmt.cloud.test/fluidcloudnative/fluid-csi:v0.9.1-16937652-arm64
docker pull birdhk/fluid-csi:v0.9.1-16937652 docker tag birdhk/fluid-csi:v0.9.1-16937652 repos-yltest-mgmt.cloud.test/fluidcloudnative/fluid-csi:v0.9.1-16937652-amd64
docker push repos-yltest-mgmt.cloud.test/fluidcloudnative/fluid-csi:v0.9.1-16937652-arm64 docker push repos-yltest-mgmt.cloud.test/fluidcloudnative/fluid-csi:v0.9.1-16937652-amd64
- 使用manifest构建并推送
docker manifest create –insecure repos-yltest-mgmt.cloud.test/fluidcloudnative/fluid-csi:v0.9.1-16937652 repos-yltest-mgmt.cloud.test/fluidcloudnative/fluid-csi:v0.9.1-16937652-arm64 repos-yltest-mgmt.cloud.test/fluidcloudnative/fluid-csi:v0.9.1-16937652-amd64 docker manifest push –insecure repos-yltest-mgmt.cloud.test/fluidcloudnative/fluid-csi:v0.9.1-16937652
#### 脚本程序
package main
import ( “fmt” “io/ioutil” “log” “os” “os/exec”
"gopkg.in/yaml.v3" )
type Config struct {
Images []string yaml:"images"
Harbor struct {
URL string yaml:"url"
Repository string yaml:"repository"
Username string yaml:"username"
Password string yaml:"password"
InsecureSkipVerify bool yaml:"insecureSkipVerify"
} yaml:"harbor"
}
func main() { // 读取配置文件 configFile := “manifest-images.yaml” // 默认文件 if len(os.Args) > 1 { configFile = os.Args[1] }
data, err := ioutil.ReadFile(configFile)
if err != nil {
log.Fatalf("读取配置文件失败: %v", err)
}
// 绑定YAML配置到结构体
var config Config
err = yaml.Unmarshal(data, &config)
if err != nil {
log.Fatalf("解析 YAML 失败: %v", err)
}
// fmt.Println(config.Harbor.URL)
// fmt.Println(config.Harbor.Repository)
// fmt.Println(config.Harbor.Username)
// fmt.Println(config.Harbor.Password)
// fmt.Println(config.Harbor.InsecureSkipVerify)
// 处理每个镜像
for _, image := range config.Images {
processImage(image, config)
} }
func processImage(image string, config Config) { arm64Tag := fmt.Sprintf(“%s/%s/%s-arm64”, config.Harbor.URL, config.Harbor.Repository, image) amd64Tag := fmt.Sprintf(“%s/%s/%s-amd64”, config.Harbor.URL, config.Harbor.Repository, image)
// 拉取、标记并推送 arm64 镜像
execCommand("docker", "pull", image, "--platform", "linux/arm64")
execCommand("docker", "tag", image, arm64Tag)
execCommand("docker", "push", arm64Tag)
// 拉取、标记并推送 amd64 镜像
execCommand("docker", "pull", image, "--platform", "linux/amd64")
execCommand("docker", "tag", image, amd64Tag)
execCommand("docker", "push", amd64Tag)
// 创建并推送 manifest
manifestCmd := []string{
"manifest", "create",
"--insecure",
fmt.Sprintf("%s/%s/%s", config.Harbor.URL, config.Harbor.Repository, image),
arm64Tag,
amd64Tag,
}
execCommand("docker", manifestCmd...)
pushManifestCmd := []string{
"manifest", "push",
"--insecure",
fmt.Sprintf("%s/%s/%s", config.Harbor.URL, config.Harbor.Repository, image),
}
execCommand("docker", pushManifestCmd...) }
func execCommand(name string, args …string) { cmd := exec.Command(name, args…) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Run() if err != nil { log.Fatalf(“命令 %s 执行失败: %v”, name, err) } }
- 配置文件如下:
cat manifest-images.yaml images:
- birdhk/fluid-csi:v0.9.1-16937652
- nginx:1.21.0 harbor: url: repos-yltest-mgmt.cloud.test repository: fluidcloudnative username: admin password: xxxx insecureSkipVerify: true

### 8、操作实例(搭建wordpress博客为例)
docker pull wordpress docker pull mysql:8
1、创建Mysql容器
docker run -d –name mysql -p 3306:3306
-v mysql-data:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=root
-e MYSQL_DATABASE=wordpress
mysql:8 –character-set-server=utf8
2、启动项目(–link到那个容器)
docker run -d -p 8080:80
–name wordpess
-e WORDPRESS_DB_HOST=192.168.6.31:3306
-e WORDPRESS_DB_USER=root
-e WORDPRESS_DB_PASSWORD=root
wordpress
访问测试:192.168.6.31:8080

## 10、镜像仓库Harbor
有时候使用 Docker Hub 这样的公共仓库可能不方便,用户可以创建一个本地仓库供私人使用。
常见的有两种:registry 和Harbor
### 1、registry
Registry是Docker的开源项目,主要用于创建个人仓库
docker run -d
-p 5000:5000
-v /opt/data/registry:/var/lib/registry
registry
上传镜像到仓库
docker tag busybox:1.28.4 127.0.0.1:5000/busybox:v1 docker push 127.0.0.1:5000/busybox:v1
用 curl 查看仓库中的镜像。
curl 127.0.0.1:5000/v2/_catalog
### 2、Harbor介绍
Harbor是构建企业级私有docker镜像的仓库的开源解决方案,它是Docker Registry的更高级封装,它除了提供友好的Web UI界面,角色和用户权限管理,用户操作审计等功能外,它还整合了K8s的插件(Add-ons)仓库。
**Harbor安装有3种方式: **
- 在线安装:从Docker Hub下载Harbor相关镜像,因此安装软件包非常小
- 离线安装:安装包包含部署的相关镜像,因此安装包比较大
- OVA安装程序:当用户具有vCenter环境时,使用此安装程序,在部署OVA后启动Harbor
### 3、Harbor部署(离线)
下载地址:https://github.com/goharbor/harbor/releases
#### 1. 安装docker-compose
获取地址:https://github.com/docker/compose/releases
Compose是一个用来定义和运行复杂应用的Docker工具。
Compose 通过一个配置文件来管理多个Docker容器,在配置文件中,所有的容器通过services来定义,然后使用docker-compose脚本来启动,停止和重启应用,和应用中的服务以及所有依赖服务的容器,非常适合组合使用多个容器进行开发的场景。
curl -L “https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)” -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose –version
#### 2. 解压配置
tar xf harbor-offline-installer-v2.4.1.tgz -C /opt
配置
cp harbor.yml.tmpl harbor.yml
**harbor.yml详解:**
https://goharbor.io/docs/2.0.0/install-config/configure-yml-file/#required-parameters
hostname设置访问地址,可以使用ip、域名,不可以设置为127.0.0.1或localhost
hostname: 192.168.6.31
HTTP相关配置(不要在生产环境中使用)
http: port: 80 # HTTP 的端口号,用于 Harbor 门户和 Docker 命令。默认值为 80。
HTTPS相关配置(需要证书可以先注释)
#https:
port: 443
certificate: /your/certificate/path # SSL 证书的路径。
private_key: /your/private/key/path # SSL 密钥的路径。
取消以下注释,harbor组件之间将使用TLS通信
internal_tls:
# set enabled to true means internal tls is enabled
enabled: true
# put your cert and key files on dir
dir: /etc/harbor/tls/internal
为 Harbor 系统管理员设置初始密码。该密码仅在Harbor 首次启动时使用。后续登录时,将忽略此设置,并在 Harbor Portal 中设置管理员密码。默认用户名和密码是admin和Harbor12345
harbor_admin_password: Harbor12345
使用本地 PostgreSQL 数据库。您可以选择配置外部数据库
database: password: root123 max_idle_conns: 100 # 空闲连接池中的最大连接数。如果设置为 <=0,则不保留空闲连接。默认值为 50。如果未配置,则值为 2。 max_open_conns: 900 # 与数据库的最大打开连接数。如果 <= 0,则打开连接的数量没有限制。对于到 Harbor 数据库的最大连接数,默认值为 100。如果未配置,则值为 0。
目标主机上存储 Harbor 数据的位置。即使删除和/或重新创建 Harbor 的容器,该数据也保持不变。
data_volume: /opt/harbor/data
配置 Trivy 扫描仪
trivy: ignore_unfixed: false # 将标志设置为true仅显示已修复的漏洞。默认值为false skip_update: false insecure: false
jobservice: max_job_workers: 10
设置 web hook 作业的最大重试次数。默认值为 10。
notification: webhook_job_max_retry: 10
chart: absolute_url: disabled
配置日志记录。Harbor 使用 rsyslog
来收集每个容器的日志。
log: level: info local: rotate_count: 50 rotate_size: 200M location: /opt/harbor/logs
_version: 2.4.0
配置要由 Clair、复制作业服务和 Harbor 使用的代理。
proxy: http_proxy: https_proxy: no_proxy: components: - core - jobservice - trivy
#### 3、安装启动
创建所需的目录
mkdir -p /opt/harbor/{data,logs}
./install.sh
#### 4、验证并访问
docker-compose ps

访问:IP:80(默认用户名和密码是admin和Harbor12345)
#### 5、Harbor的基本使用
**登陆方式:**`docker login -u admin -p Harbor12345 http://127.0.0.1`
关闭harbor
docker-compose down -v
启动harbor
docker-compose up -d
```
新建项目并上传下载测试
6、Harbor高可用
参考连接:https://www.yuque.com/docs/share/8f8d1f9d-ae30-46fa-84d2-6845d1075a15?#