docker
目录
- docker介绍
- 安装和配置文件详解
- 镜像与容器相关操作
- dockerFile指令
- dockerFile实现镜像自动化构建
- 实现数据持久化
- 实现容器间通信和网络
- docker-compose单机编排工具
- 搭建harbor私有仓库
docker介绍
Docker 的组成
Docker 主机(Host): 一个物理机或虚拟机,用于运行Docker服务进程和容器,也称为宿主机,
node节点
Docker 服务端(Server): Docker守护进程,运行docker容器
Docker 客户端(Client): 客户端使用 docker 命令或其他工具调用docker API
Docker 镜像(Images): 镜像可以理解为创建实例使用的模板,本质上就是一些程序文件的集合
Docker 仓库(Registry): 保存镜像的仓库,官方仓库: https://hub.docker.com/,可以搭建私有仓库
harbor
Docker 容器(Container): 容器是从镜像生成对外提供服务的一个或一组服务,其本质就是将镜像中
的程序启动后生成的进程
Namespace
namespace是Linux系统的底层概念,在LInux内核层实现,即有一些不同类型的命名空间被部署在内
核,各个docker容器运行在同一个docker主进程并且共用同一个宿主机系统内核,各docker容器运行在
宿主机的用户空间,每个容器都要有类似于虚拟机一样的相互隔离的运行空间,但是容器技术是在一个
进程内实现运行指定服务的运行环境,并且还可以保护宿主机内核不受其他进程的干扰和影响。
隔离类型 | 功能 | 系统调用参数 | 内核版本 |
---|---|---|---|
MNT Namespace(mount) | 提供磁盘挂载点和文件系统的隔离能力 | CLONE_NEWNS | 2.4.19 |
IPC Namespace(InterProcess Communication) | 提供进程间通信的隔离能力,包括信号量,消息队列和共享内存 | CLONE_NEWIPC | 2.6.19 |
UTS Namespace(UNIXTimesharing System) | 提供内核,主机名和域名隔离能力 | CLONE_NEWUTS | 2.6.19 |
PID Namespace(ProcessIdentification) | 提供进程隔离能力 | CLONE_NEWPID | 2.6.24 |
Net Namespace(network) | 提供网络隔离能力,包括网络设备,网络栈,端口等 | CLONE_NEWNET | 2.6.29 |
User Namespace(user) | 提供用户隔离能力,包括用户和组 | CLONE_NEWUSER | 3.8 |
Pid namespace
- 不同用户的进程就是通过Pid namespace 隔离开的,且不同namespace 中可以有相同Pid。
- 有了Pid namespace, 每个namespace 中的Pid 能够相互隔离。
net namespace
- 网络隔离是通过net namespace 实现的, 每个net namespace 有独立的network devices, IP
- addresses, IP routing tables, /proc/net 目录。
- Docker 默认采用veth 的方式将container 中的虚拟网卡同host 上的一个docker bridge: docker0
- 连接在一起。
ipc namespace
- Container 中进程交互还是采用linux 常见的进程间交互方法(interprocess communication –
- IPC), 包括常见的信号量、消息队列和共享内存。
- container 的进程间交互实际上还是host上具有相同Pid namespace 中的进程间交互,因此需要在
- IPC 资源申请时加入namespace 信息- 每个IPC 资源有一个唯一的32 位ID。
mnt namespace
- mnt namespace 允许不同namespace 的进程看到的文件结构不同,这样每个namespace 中的进
- 程所看到的文件目录就被隔离开了
uts namespace
- UTS(“UNIX Time-sharing System”) namespace允许每个container 拥有独立的hostname 和
- domain name, 使其在网络上可以被视作一个独立的节点而非Host 上的一个进程。
user namespace
- 每个container 可以有不同的user 和group id, 也就是说可以在container 内部用container 内部的
- 用户执行程序而非Host 上的用户。
一个宿主机运行了N个容器,多个容器共用一个 OS,必然带来的以下问题:
- 怎么样保证每个容器都有不同的文件系统并且能互不影响?
- 一个docker主进程内的各个容器都是其子进程,那么如果实现同一个主进程下不同类型的子进程?
- 各个容器子进程间能相互通信(内存数据)吗?
- 每个容器怎么解决IP及端口分配的问题?
- 多个容器的主机名能一样吗?
- 每个容器都要不要有root用户?怎么解决账户重名问题?
Podman 和docker不同之处
- docker 需要在系统上运行一个守护进程(docker daemon),这会产生一定的开销,而podman 不需要。
- 启动容器的方式不同: docker cli 命令通过API跟 Docker Engine(引擎) 交互告诉它我想创建一个container,然后docker Engine 才会调用 OCI container runtime(runc) 来启动一个container。这代表container的process(进程)不会是 Docker CLI 的 child process(子进程) ,而是 Docker Engine 的 child process 。
- Podman 是直接给 OCI containner runtime(runc) 进行交互来创建container的,所以container process 直接是 podman 的 child process 。
- 因为docke有docker daemon,所以docker启动的容器支持 --restart 策略,但是podman不支持
- docker需要使用root用户来创建容器。 这可能会产生安全风险,尤其是当用户知道docker run命令的--privileged选项时。podman既可以由root用户运行,也可以由非特权用户运行
- docker在Linux上作为守护进程运行扼杀了容器社区的创新。 如果要更改容器的工作方式,则需要更改docker守护程序并将这些更改推送到上游。 没有守护进程,容器基础结构更加模块化,更容
易进行更改。 podman的无守护进程架构更加灵活和安全。
Docker 的优势
- 快速部署: 短时间内可以部署成百上千个应用,更快速交付到线上
- 高效虚拟化: 不需要额外hypervisor支持,基于linux内核实现应用虚拟化,相比虚拟机大幅提高性能和效率
- 节省开支: 提高服务器利用率,降低IT支出
- 简化配置: 将运行环境打包保存至容器,使用时直接启动即可
- 环境统一: 将开发,测试,生产的应用运行环境进行标准化和统一,减少环境不一样带来的各种问题
- 快速迁移和扩展: 可实现跨平台运行在物理机、虚拟机、公有云等环境,良好的兼容性可以方便将应用从A宿主机迁移到B宿主机,甚至是A平台迁移到B平台
- 更好的实现面向服务的架构,推荐一个容器只运行一个应用,实现分布的应用模型,可以方便的进行横
向扩展,符合开发中高内聚,低耦合的要求,减少不同服务之间的相互影响。
Docker 的缺点
- 多个容器共用宿主机的内核,各应用之间的隔离不如虚拟机彻底
- 由于和宿主机之间的进程也是隔离的,需要进入容器查看和调试容器内进程等资源,变得比较困难和繁琐
- 如果容器内进程需要查看和调试,需要在每个容器内都需要安装相应的工具,这也造成存储空间的重
复浪费
Docker 的运行机制
镜像仓库 Registry
统一保存镜像而且是多个不同镜像版本的地方,叫做镜像仓库。
- Docker hub: docker官方的公共仓库,已经保存了大量的常用镜像,可以方便大家直接使用
- 阿里云,网易等第三方镜像的公共仓库
- Image registry: docker 官方提供的私有仓库部署工具,无web管理界面,目前使用较少
- Harbor: vmware 提供的自带web界面自带认证功能的镜像私有仓库,目前有很多公司使用
安装和配置文件详解
Docker版本选择
github地址: https://github.com/moby/moby
- Docker版本号之前一直是0.X版本或1.X版本,从2013年3月13日发布第一个版本0.1.1-1开始一直到2017年02月08日发布1.13.1版
- 从2017年3月1号开始改为每个季度发布一次稳定版,其版本号规则也统一变更为YY.MM.xx,第一个版本为17.03.0, 例如17.09表示是2017年9月份发布的
安装和删除方法
阿里云文档: https://developer.aliyun.com/mirror/docker-ce?spm=a2c6h.13651102.0.0.3e221b11gu
HCWE
Ubuntu22.04 安装和删除Docker
# 安装必要的一些系统工具
[root@ubuntu ~]#sudo apt-get update
[root@ubuntu ~]#sudo apt-get -y install apt-transport-https ca-certificates curl softwareproperties-common
# 安装GPG证书
[root@ubuntu ~]#curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key
add -
# 添加阿里云仓库
[root@ubuntu ~]#sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/dockerce/linux/ubuntu $(lsb_release -cs) stable"
# 更新并安装Docker-CE
[root@ubuntu ~]#sudo apt-get -y update
[root@ubuntu ~]#sudo apt-get -y install docker-ce
# 安装指定版本的Docker-CE
#查看docker版本
[root@ubuntu ~]#apt-cache madison docker-ce
#Ubuntu22.04安装指定版本
[root@ubuntu ~]#apt -y install docker-ce=5:24.0.6-1~ubuntu.22.04~jammy docker-ce-cli=5:24.0.6-
1~ubuntu.22.04~jammy
# 删除docker
[root@ubuntu ~]#apt purge docker-ce
[root@ubuntu ~]#rm -rf /var/lib/docker
CentOS 安装和删除Docker
#查看linux内核
[root@rocky8 ~]# uname -a
#更新yum包(测试环境可随意操作,生产环境酌情慎重更新)
[root@rocky8 ~]# yum update
#安装需要的软件包
[root@rocky8 ~]# yum install -y yum-utils device-mapper-persistent-data lvm2
#设置yum源
[root@rocky8 ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#查看所有仓库中所有docker版本,并选择特定版本安装
[root@rocky8 ~]# yum list docker-ce --showduplicates | sort -r
#指定版本安装
[root@rocky8 ~]# yum install docker-ce-18.03.1.ce
#删除docker
[root@rocky8 ~]# yum remove docker-ce
#删除docker资源存放的相关文件
[root@rocky8 ~]# rm -rf /var/lib/docker
查看 docker 详解信息
[root@ubuntu ~]#docker info
Client:
Debug Mode: false #client 端是否开启 debug
Server:
Containers: 2 #当前主机运行的容器总数
Running: 0 #有几个容器是正在运行的
Paused: 0 #有几个容器是暂停的
Stopped: 2 #有几个容器是停止的
Images: 4 #当前服务器的镜像数
Server Version: 19.03.5 #服务端版本
Storage Driver: overlay2 #正在使用的存储引擎
Backing Filesystem: extfs #后端文件系统,即服务器的磁盘文件系统
Supports d_type: true #是否支持 d_type
Native Overlay Diff: true #是否支持差异数据存储
Logging Driver: json-file #日志类型,每个容器的标准输出以日志存放
在/var/lib/docker/containers/<CONTAINER ID>/<CONTAINER ID>-json.log
Cgroup Driver: cgroupfs #Cgroups 类型
Plugins: #插件
Volume: local #卷
Network: bridge host ipvlan macvlan null overlay # overlay 跨主机通信
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk
syslog # 日志类型
Swarm: inactive #是否支持 swarm
Runtimes: runc #已安装的容器运行时
Default Runtime: runc #默认使用的容器运行时
Init Binary: docker-init #初始化容器的守护进程,即 pid 为 1 的进程
containerd version: b34a5c8af56e510852c35414db4c1f4fa6172339 #版本
runc version: 3e425f80a8c931f88e6d94a8c831b9d5aa481657 #runc 版本
init version: fec3683 #init 版本
Security Options: #安全选项
apparmor #安全模块,https://docs.docker.com/engine/security/apparmor/
seccomp #安全计算模块,即制容器操作,
https://docs.docker.com/engine/security/seccomp/
Profile: default #默认的配置文件
Kernel Version: 4.15.0-29-generic #宿主机内核版本
Operating System: Ubuntu 18.04.1 LTS #宿主机操作系统
OSType: linux #宿主机操作系统类型
Architecture: x86_64 #宿主机架构
CPUs: 1 #宿主机 CPU 数量
Total Memory: 962MiB #宿主机总内存
Name: ubuntu1804.wang.org #宿主机 hostname
ID: IZHJ:WPIN:BRMC:XQUI:VVVR:UVGK:NZBM:YQXT:JDWB:33RS:45V7:SQWJ #宿主机 ID
Docker Root Dir: /var/lib/docker #宿主机关于docker数据的保存目录,建议使用独立SSD的磁
盘,保证性能和空间
Debug Mode: false #server 端是否开启 debug
Labels:
Experimental: false #是否测试版
Insecure Registries:
127.0.0.0/8 : #非安全的镜像仓库
Registry Mirrors:
https://si7y70hh.mirror.aliyuncs.com/ #镜像仓库
Live Restore Enabled: false #是否开启活动重启 (重启docker-daemon 不关闭容器 )
WARNING: No swap limit support #系统警告信息 (没有开启 swap 资源限制 )
docker基础命令
#启动docker(客户端)
systemctl start docker
#启动守护进程
systemctl start docker.service
#查看docker版本
docker version
#列出正在运行的容器
1.docker ps
#列出所有镜像
2.docker image ls
#创建容器
3.docker container create 镜像id/名称
#启动容器
4.docker container start 容器id/名称
#进入正在运行的容器
5.docker exec -it 容器id/名称 /bin/bash
#停止容器
6.docker container stop
#删除容器
7.docker container rm 容器id/名称
#删除镜像
8.docker image rm 镜像id/名称
#启动容器
9.docker container start 容器id/名称
#列出容器详细信息
10.docker inspect 容器id/名称
#复制容器内的文件到宿主机
11.docker cp nginx:/etc/nginx/conf.d/default.conf /home/nginx/conf/
#设置开机自启动
12.docker update restart=always nginx
docker配置文件
一般来说是没有这两个配置文件的,需要自己创建。且docker要做镜像加速才能拉取镜像。
#docker-ce 配置文件
/etc/docker/daemon.json
#Docker Registry配置文件
/etc/containers/registries.conf
#配置信息
[root@ubuntu2004 ~]#vim /etc/docker/daemon.json
{
"registry-mirrors": [
"https://registry.docker-cn.com",
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn", #镜像加速
"https://si7y70hh.mirror.aliyuncs.com/"
],
#开启远程:https://docs.docker.com/config/daemon/remote-access/ 或者
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H fd://
"hosts": ["unix:///var/run/docker.sock", "tcp://10.0.0.10:2375"],
"insecure-registries": ["harbor.wang.org"],
"exec-opts": ["native.cgroupdriver=systemd"],
"graph": "/data/docker", #指定docker数据目录,新版24.0.0不支持,实现:
ExecStart=/usr/bin/dockerd --data-root=/data/docker
"max-concurrent-downloads": 10,
"max-concurrent-uploads": 5,
"log-opts": {
"max-size": "300m", #指定容器日志文件的最大值
"max-file": "2" #指定容器日志文件的个数,循环写入日志文件,即一个日志满,会写入第二
个文件
},
"live-restore": true, #docker.service重启,不影响容器的运行
"proxies": { #代理 https://docs.docker.com/network/proxy/
"default": {
"httpProxy": "http://proxy.example.com:3128",
"httpsProxy": "https://proxy.example.com:3129",
"noProxy": "*.test.example.com,.example.org,127.0.0.0/8"
}
"tcp://docker-daemon1.example.com": {
"noProxy": "*.internal.example.net"
}
}
}
注意:这种方式只对新建的容器有效的,之前的容器不生效
[root@ubuntu ~]#systemctl daemon-reload && systemctl restart docker.service
镜像加速配置和优化
阿里云获取加速地址:
浏览器打开,注册或登录阿里云账号,点击左侧的镜像加速器,将会得到
一个专属的加速地址,而且下面有使用配置说明
[root@ubuntu ~]vim /etc/docker/daemon.json
{
"registry-mirrors" : [
"http://registry.docker-cn.com",
"http://docker.mirrors.ustc.edu.cn", #镜像加速
"http://hub-mirror.c.163.com"
],
"insecure-registries" : [
"registry.docker-cn.com",
"docker.mirrors.ustc.edu.cn"
],
"debug" : true,
"experimental" : true
}
[root@ubuntu ~]#systemctl daemon-reload
[root@ubuntu ~]#systemctl restart docker
docker代理功能
[root@ubuntu ~]#mkdir -p /etc/systemd/system/docker.service.d
[root@ubuntu ~]#cat >> /etc/systemd/system/docker.service.d/http-proxy.conf
<<EOF
[Service]
Environment="HTTP_PROXY=http://${PROXY_SERVER_IP}:${PROXY_PORT}/"
Environment="HTTPS_PROXY=http://${PROXY_SERVER_IP}:${PROXY_PORT}/"
Environment="NO_PROXY=127.0.0.0/8,172.17.0.0/16,10.0.0.0/24,10.244.0.0/16,192.16
8.0.0/16,mqh.org,cluster.local"
EOF
[root@ubuntu ~]#systemctl daemon-reload && systemctl restart docker.service
开启远程连接
#在docker服务端主机开启远程网络连接功能
[root@ubuntu ~]#vim /lib/systemd/system/docker.service
[Service]
.....
ExecStart=/usr/local/bin/dockerd -H unix://var/run/docker.sock -H
tcp://0.0.0.0:2375
.......
[root@ubuntu ~]#systemctl daemon-reload
[root@ubuntu ~]#systemctl restart docker.service
#确认端口打开
[root@ubuntu2204 ~]#ss -ntlp|grep dockerd
LISTEN 0 4096 *:2375 *:* users:
(("dockerd",pid=1937,fd=3))
[root@ubuntu ~]#docker info
.......
127.0.0.0/8
Live Restore Enabled: false
Product License: Community Engine
#显示下面提示
WARNING: API is accessible on http://0.0.0.0:2375 without encryption.
Access to the remote API is equivalent to root access on the host.
Refer
to the 'Docker daemon attack surface' section in the documentation for
more information: https://docs.docker.com/go/attack-surface/
#在另一台docker客户端主机远程连接服务器
[root@ubuntu ~]#docker -H <docker服务器IP>:2375 version
镜像与容器相关操作
镜像相关指令
#查看本地镜像
[root@ubuntu ~]#docker images
#查看指定镜像的详细信息
[root@ubuntu ~]#docker inspect nginx:1.24
#镜像导出
[root@ubuntu ~]#docker save mysql:5.7.30 alpine:3.11.3 > /data/myimages.tar
#导出镜像并压缩
[root@ubuntu ~]#docker save rockylinux:9.1-minimal | gzip - > rockylinux-
9.1-minimal.tar.gz
#导出所有镜像并打包压缩
[root@ubuntu ~]#docker save `docker images | awk 'NR!=1{print $1":"$2}'` |
gzip > all.tar.gz
#镜像导入
[root@ubuntu ~]#docker load -i /data/myimages.tar
#将一台主机的所有镜像传到另一台主机
[root@ubuntu ~]#docker save `docker images | awk 'NR!=1{print $1":"$2}'` -o
backup.tar
[root@ubuntu ~]#scp backup.tar 192.168.93.200:/data
root@ubuntu:~# docker load -i backup.tar
#删除镜像
[root@ubuntu ~]#docker rmi alpine:3.11.3
#删除所有不再使用的镜像
[root@ubuntu ~]#docker rmi -f `docker images -q`
#镜像打标签
[root@ubuntu ~]#docker images
REPOSITORY TAG IMAGE ID CREATED
SIZE
alpine latest e7d92cdc71fe 11 days ago
5.59MB
[root@ubuntu ~]#docker tag alpine alpine:3.11
[root@ubuntu ~]#docker images
REPOSITORY TAG IMAGE ID CREATED
SIZE
alpine 3.11 e7d92cdc71fe 11 days ago
5.59MB
alpine latest e7d92cdc71fe 11 days ago
5.59MB
容器相关指令
容器启动流程
Docker容器如果希望启动后能持续运行,就必须有一个能前台持续运行的进程,如果在容器中启动传统的服务,如:httpd,php-fpm等均为后台进程模式运行,就导致 docker 在前台没有运行的应用,这样的容器启动后会立即退出。所以一般会将服务程序以前台方式运行,对于有一些可能不知道怎么实现前台运行的程序,只需要在你启动的该程序之后添加类似于 tail ,top 这种可以前台运行的程序即可. 比较常用的方法,如 tail -f /etc/hosts
。
从COMMAND可以看出,alpine的默认命令是/bin/sh,不符合“前台”这个条件。而为什么nginx不指定却可以直接运行,是因为nginx的默认命令里的这一长串其实是一个脚本,里面定义了一个前台的,可持续运行的进程。
[root@localhost docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c27fe34a621b alpine "/bin/sh" 31 seconds ago Exited (0) 30 seconds ago sleepy_boyd
de3be27b7008 nginx "/docker-entrypoint.…" 18 minutes ago Exited (0) 18 minutes ago heuristic_varahamihira
ba87186ef07b hello-world "/hello" 42 minutes ago Exited (0) 42 minutes ago sweet_wescoff
docker start|stop|restart|pause|unpause 容器ID/名称
#指定容器名称
[root@ubuntu ~]#docker run --name alpine alpine
#启动并进入容器
[root@ubuntu ~]docker run -it alpine sh
exit #退出容器,容器退出即停止(ctrl+p+q退出后容器不会停止)
exec命令:在运行中的容器启动新进程,可以执行单次命令,以及进入容器
#进入容器,执行命令,exit退出但容器不停止
[root@ubuntu1804 ~]#docker exec -it nginx bash
#停止容器
[root@ubuntu ~]#docker stop nginx
#强制关闭所有运行中的容器
[root@ubuntu ~]#docker kill `docker ps -a -q`
#后台运行容器
[root@localhost docker]# docker run -d nginx
615e99b8b3124448946572d15eb16b6df5edab564e3b0b3632cd858e870904ef
#显示运行的容器
[root@localhost docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
615e99b8b312 nginx "/docker-entrypoint.…" 8 seconds ago Up 7 seconds 80/tcp happy_goldberg
#显示全部容器,包括退出状态的容器
[root@localhost docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
615e99b8b312 nginx "/docker-entrypoint.…" 11 minutes ago Up 11 minutes 80/tcp happy_goldberg
c27fe34a621b alpine "/bin/sh" 24 minutes ago Exited (0) 24 minutes ago sleepy_boyd
#删除所有容器
[root@ubuntu ~]#docker rm -f `docker ps -a -q`
#删除所有状态为exited的容器
[root@ubuntu ~]#docker rm `docker ps -qf status=exited`
#清除不再使用的镜像
[root@ubuntu ~]#docker system prune -f -a
#查看容器的详细信息
[root@localhost docker]# docker inspect nginx
#容器启动后,默认处于预定义的NAT网络中,所以外部网络的主机无法直接访问容器中网络服务,因此需要做端口暴露
#以rbbitmq为例:
[root@localhost docker]# docker run -p 15672:15672 -p 5672:5672 --name rabbitmq \
> --restart=always \
> --privileged=true \
> -v /home/docker/rabbit/data:/var/lib/rabbitmq \
> -e RABBITMQ_DEFAULT_USER=rabbit \
> -e RABBITMQ_DEFAULT_PASS=rabbit@123456 \
> -d rabbitmq:3-management
#参数说明
-p 15672:15672 -p 5672:5672 映射端口(第一个15672是宿主机的,第二个15672是容器内的)
--name rabbitmq 指定容器名称
--restart always 容器自启
--privileged=true 提升容器内权限
-v /home/docker/rabbit/data:/var/lib/rabbitmq 映射数据目录(同理,前面的目录是宿主机的)
-e RABBITMQ_DEFAULT_USER=rabbit 创建用户名
-e RABBITMQ_DEFAULT_PASS=rabbit@123456 创建密码
-d rabbitmq:3-management 指定后台运行-镜像名称
docker日志
docker 日志是存放在宿主机的 /var/lib/docker/containers/<container_id>/<container_id>-json.log文件中
docker logs 容器id
docker logs --tail 3 容器id
#显示时间
docker logs --tail 0 -t 容器id
#持续跟踪
docker logs -f 容器id
dockerFile指令
DockerFile 是一种被Docker程序解释执行的脚本,由一条条的命令组成的,每条命令对应linux下面的一条命令,Docker程序将这些DockerFile指令再翻译成真正的linux命令,其有自己的书写方式和支持的命令,Docker程序读取DockerFile并根据指令生成Docker镜像。请注意,每条指令都是独立运行的,并会导致创建新镜像,比如 RUN cd /tmp 对下一条指令不会有任何影响。
Dockerfile 文件说明
- 每一行以Dockerfile的指令开头,指令不区分大小写,但是惯例使用大写
- 使用 # 开始作为注释
- 每一行只支持一条指令,每条指令可以携带多个参数
- 指令按文件的顺序从上至下进行执行
- 每个指令的执行会生成一个新的镜像层,为了减少分层和镜像大小,尽可能将多条指令合并成一条指令
- 制作镜像一般可能需要反复多次,每次执行dockfile都按顺序执行,从头开始,已经执行过的指令已经缓存,不需要再执行,如果后续有一行新的指令没执行过,其往后的指令将会重新执行,所以为加速镜像制作,将最常变化的内容放下dockerfile的文件的后面。
Dockerfile 相关指令
FROM #定义基础镜像,指定从哪一个镜像为基础镜像来构建新的镜像
MAINTAINER #定义镜像的作者信息,可以省略不写
ADD #复制文件指令并自动解压,后面跟本地文件或者网络上的URL地址
COPY #复制文件指令,类似ADD,但是COPY指令不具备自动解压功能
ENV #设置容器变量,常用于向容器内传递用户密码等
EXPOSE #向外开发的端口,多个端口用空格间隔开
LABEL #
STOPSIGNAL #
USER #指定此镜像启动容器时候的运行用户和UID,后面的RUN命令使用此用户执行
VOLUME #设置容器挂载宿主机的目录(匿名卷)
WORKDIR #指定容器的工作目录
RUN #构建镜像时运行的shell命名
CMD #容器启动运行的命令,每个Dockerfile只能有一条,如果有多条则执行最后一条
dockerfile格式:
# 使用官方镜像作为基础镜像,from必须为第一行
FROM nginx:1.24
#指定镜像元数据,如作者名,版本等
LABEL maintainer="mqh <root@mqh.com>"
LABEL version="1.0"
# 设置工作目录
WORKDIR /data/dockerfile/web/nginx
# 支持自动解压缩。可以将复制指定的到容器中
ADD test relativeDir/ # adds "test" to `WORKDIR`/relativeDir/
ADD test /absoluteDir/ # adds "test" to /absoluteDir/
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /
#ENV 可以定义环境变量和值,会被后续指令(如:ENV,ADD,COPY,RUN等)通过$KEY或${KEY}进行引用,并在容器运行时保持
ENV NAME meng qing
RUN touch $NAME.txt
#RUN 指令用来在构建镜像阶段需要执行 FROM 指定镜像所支持的Shell命令
#RUN 可以写多个,建议多个RUN写成一条指令
#每个RUN都是独立运行的,和前一个RUN无关
RUN yum -y install epel-release \
&& yum -y install nginx \
&& rm -rf /usr/share/nginx/html/*
&& echo "<h1> docker test nginx </h1>" > /usr/share/nginx/html/index.html
# 暴露应用程序监听的端口
EXPOSE 80
# 不指定则会使用默认命令
# RUN 命令是在构建镜像时执行的命令
# 如果用户启动容器时用 docker run xxx 指定运行的命令,则会覆盖 CMD 指定的命令
CMD ["nginx", "-g", "daemon off;"]
举例:
[root@ubuntu dockerfile]#cat Dockerfile
FROM ubuntu:22.04
LABEL maintainer="mqh <root@mqh.com>"
RUN apt update \
&& apt -y install curl \
&& rm -rf /var/lib/apt/lists/*
CMD [ "curl", "-s","https://ip.cn"]
dockerFile实现镜像自动化构建
#按照业务类型或系统类型等方式划分创建目录环境,方便后期镜像比较多的时候进行分类
[root@localhost docker]# tree /data/dockerfile/
/data/dockerfile/
├── system
│ ├── alpine
│ ├── centos
│ ├── debian
│ └── ubuntu
└── web
├── jdk
├── kafka
├── mysql
└── nignx
[root@ubuntu ~]#cat /data/Dockerfile
FROM centos
LABEL maintainer="mqh <root@mqh.com>"
RUN yum install -y nginx && echo Nginx Website in Docker >
/usr/share/nginx/html/index.html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
#使用build构建镜像
[root@ubuntu ~]#docker build -t nginx_centos8.2:v1.14.1 /data/
[root@ubuntu ~]#docker run -d -P --name nginx-web nginx_centos8.2:v1.14.1
实现数据持久化
容器的数据分层目录
- LowerDir: image 镜像层,即镜像本身,只读
- UpperDir: 容器的上层,可读写 ,容器变化的数据存放在此处
- MergedDir: 容器的文件系统,使用Union FS(联合文件系统)将lowerdir 和 upperdir 合并完成
- 后给容器使用,最终呈现给用户的统一视图
- WorkDir: 容器在宿主机的工作目录,挂载后内容会被清空,且在使用过程中其内容用户不可见
容器数据持久保存方式
-
卷(Volume)
这是 Docker 推荐的挂载方式。卷是完全由 Docker 管理的文件目录,可以在容器之间共享和重用。在创建卷时,Docker 创建了一个目录在宿主机上,然后将这个目录挂载到容器内。 -
绑定挂载(Bind Mount):
这种方式可以将宿主机上的任意文件或目录挂载到容器内。与卷不同,绑定挂载依赖于宿主机的文件系统结构。 -
tmpfs 挂载
tmpfs 挂载不与宿主机上的任何文件或目录相关联,而是将一个临时文件系统挂载到容器的某个目录下。这种方式的主要优点是它提供了一个高速且安全的挂载方式,因为 tmpfs 挂载通常驻留在宿主机的内存中,且在容器停止后会被自动删除。
数据卷使用场景
- 数据库
- 日志输出
- 静态web页面
- 应用配置文件
- 多容器间目录或文件共享
数据卷的特点
- 数据卷是目录或者文件,并且可以在多个容器之间共同使用,实现容器之间共享和重用
- 对数据卷更改数据在所有容器里面会立即更新。
- 数据卷的数据可以持久保存,即使删除使用使用该容器卷的容器也不影响。
- 在容器里面的写入数据不会影响到镜像本身,即数据卷的变化不会影响镜像的更新
- 依赖于宿主机目录,宿主机出问题,上面容器会受影响,当宿主机较多时,不方便统一管理
- 匿名和命名数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,会拷贝到新初始化的数据卷中
数据卷分类
启动容器时,可以指定使用数据卷实现容器数据的持久化,数据卷有三种:
- 指定宿主机目录或文件: 指定宿主机的具体路径和容器路径的挂载关系,此方式不会创建数据卷
- 匿名卷: 不指定数据名称,只指定容器内目录路径充当挂载点,docker自动指定宿主机的路径进行挂载,此方式会创建匿名数据卷,Dockerfile中VOLUME指定的卷即为此种
- 命名卷: 指定数据卷的名称和容器路径的挂载关系,此方式会创建命名数据卷
绑定挂载和数据卷的区别
绑定挂载:
适用于开发环境中快速迭代代码或配置文件,比如日志文件、配置文件等。
数据卷:
- 适合用于需要持久化保存的数据,如数据库文件、应用程序生成的日志等。
- 在多容器环境下共享数据时非常有用,例如微服务架构中不同服务之间的数据交互。
- 当希望简化数据备份、恢复或迁移过程时
数据卷使用方法
绑定挂载(Bind Mount)
#指定宿主机目录或文件格式:
-v <宿主机绝对路径的目录或文件>:<容器目录或文件>[:ro] #将宿主机目录挂载容器目录,两个目录都可自动创建
#注意:如果初始容器中有旧数据,将被宿主机目录覆盖
#注意:如果扗载文件,必须指定文件的相对或绝对路径,否则会将文件名当成命名卷
#举例:
docker run -v /host/path:/container/path ...
匿名卷
匿名卷,只指定容器内路径,没有指定宿主机路径信息,宿主机自动生成/var/lib/docker/volumes/<卷ID>/_data目录,并挂载至容器指定路径
#注意:如果初始容器中有旧数据,将被复制到宿主机数据卷目录
-v <容器内路径>
#示例:
docker run --name nginx -v /etc/nginx nginx
命名卷
#命名卷将固定的存放在/var/lib/docker/volumes/<卷名>/_data
#注意:如果初始容器中有旧数据,将被复制到宿主机数据卷目录
-v <卷名>:<容器目录路径>
#可以通过以下命令事先创建,如可没有事先创建卷名,docker run时也会自动创建卷
docker volume create <卷名>
#示例:
docker volume create vol1 #也可以事先不创建
docker run -d -p 80:80 --name nginx01 -v vol1:/usr/share/nginx/html nginx
查看数据卷的挂载关系
docker inspect --format="{{.Mounts}}" <容器ID>
删除所有数据卷
docker volume rm `docker volume ls -q
#删除不再使用的数据卷
docker volume prune -f
实现容器间通信和网络
Docker服务安装完成之后,默认在每个宿主机会生成一个名称为docker0的网卡其IP地址都是172.17.0.1/16
[root@localhost docker]# ip a
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:76:a0:50:d7 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:76ff:fea0:50d7/64 scope link
valid_lft forever preferred_lft forever
#新建一个容器,在宿主机的会生成一个新网卡,和容器成对儿的出现
[root@localhost docker]# ip a
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:76:a0:50:d7 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:76ff:fea0:50d7/64 scope link
valid_lft forever preferred_lft forever
27: veth6b23973@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 0e:87:e5:e7:6b:bc brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::c87:e5ff:fee7:6bbc/64 scope link
valid_lft forever preferred_lft forever
#查看nginx的ip地址
[root@localhost docker]# docker inspect 8ce
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"DriverOpts": null,
"DNSNames": null
修改默认docker0网桥的网络配置
[root@ubuntu ~]#cat /etc/docker/daemon.json
{
"bip": "192.168.100.1/24",
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"]
}
[root@ubuntu ~]#systemctl restart docker.service
使用容器名称进行容器间通信
#指定该容器名称为 server1
[root@ubuntu ~]#docker run -it --name server1 --rm alpine:3.11 sh
#--link 利用第一个容器名称进行访问
[root@ubuntu ~]#docker run -it --rm --name server2 --link server1 alpine:3.11 sh
#别名引用 server1:server1-alias
[root@ubuntu1804 ~]#docker run -it --rm --name server3 --link server1:server1-alias alpine:3.11 sh
实现 wordpress 和 MySQL 两个容器互连
[root@centos7 ~]#docker run --name mysql \
> -v /root/lamp_docker/mysql/:/etc/mysql/conf.d \
> -v /data/mysql:/var/lib/mysql \
> --env-file=/root/lamp_docker/env_mysql.list\
> -d -p 3306:3306 mysql:8.0.29-oracle
[root@centos7 ~]#docker run -d --name wordpress --link mysql \
> -v /data/wordpress:/var/www/html/wp-content \
> --env-file=/root/lamp_docker/env_wordpress.list \
> -p 80:80 wordpress:php7.4-apache
docker五种网络模式
- none
- bridge
- container
- host
- network-name
网络模式指定
默认新建的容器使用Bridge模式,创建容器时,docker run 命令使用以下选项指定网络模式
docker run --network <mode>
docker run --net=<mode>
<mode>: 可以是以下值
none
bridge
host
container:<容器名或容器ID>
<自定义网络名称>
Bridge模式
此模式创建的容器会为每一个容器分配自己的网络 IP 等信息,并将容器连接到一个虚拟网桥与外界通信,可以和外部网络之间进行通信,通过SNAT访问外网,使用DNAT可以让容器被外部主机访问,所以此模式也称为NAT模式,此模式宿主机需要启动ip_forward功能。
bridge网络模式特点:
- 网络资源隔离: 不同宿主机的容器无法直接通信,各自使用独立网络
- 无需手动配置: 容器默认自动获取172.17.0.0/16的IP地址,此地址可以修改
- 可访问外网: 利用宿主机的物理网卡,SNAT连接外网
- 外部主机无法直接访问容器: 可以通过配置DNAT接受外网的访问
- 低性能较低: 因为可通过NAT,网络转换带来更的损耗
- 端口管理繁琐: 每个容器必须手动指定唯一的端口,容器产生端口冲容
查看bridge模式信息
[root@ubuntu ~]#docker network inspect bridge
修改Bridge网络配置方法
[root@ubuntu ~]#vim /etc/docker/daemon.json
{
"hosts": ["tcp://0.0.0.0:2375", "fd://"],
"bip": "192.168.100.100/24", #分配docker0网卡的IP,24是容器IP的netmask
"fixed-cidr": "192.168.100.128/26", #分配容器IP范围,26不是容器IP的子网掩码,只表示地址
范围
"fixed-cidr-v6": "2001:db8::/64",
"mtu": 1500,
"default-gateway": "192.168.100.200", #网关必须和bip在同一个网段
"default-gateway-v6": "2001:db8:abcd::89",
"dns": [ "1.1.1.1", "8.8.8.8"]
}
[root@ubuntu ~]#systemctl daemon-reload
[root@ubuntu ~]#systemctl restart docker
host模式
如果指定host模式启动的容器,那么新创建的容器不会创建自己的虚拟网卡,而是直接使用宿主机的网卡和IP地址访问容器的时候直接使用宿主机IP+容器端口即可,不过容器内除网络以外的其它资源,如: 文件系统、系统进程等仍然和宿主机保持隔离。适用于运行容器端口比较固定的业务。
Host 网络模式特点:
- 使用参数 --network host 指定
- 共享宿主机网络
- 各容器网络无隔离
- 网络性能无损耗
- 网络故障排除相对简单
- 容易产生端口冲突
- 网络资源无法分别统计
- 不支持端口映射
#创建host模式的容器,创建完后宿主机上的80端口会打开
[root@ubuntu1804 ~]#docker run -d --network host --name web1 nginx-centos7-base:1.6.1
none模式
在使用 none 模式后,Docker 容器不会进行任何网络配置,没有网卡、没有IP也没有路由,因此默认无法与外界通信,需要手动添加网卡配置IP等,所以极少使用。
none模式特点:
- 使用参数 --network none 指定
- 默认无网络功能,无法和外部通信
- 无法实现端口映射
- 适用于测试环境
Container 模式
使用此模式创建的容器需指定和一个已经存在的容器共享一个网络,而不是和宿主机共享网络,新创建的容器不会创建自己的网卡也不会配置自己的IP,而是和一个被指定的已经存在的容器共享IP和端口范围,因此这个容器的端口不能和被指定容器的端口冲突,除了网络之外的文件系统、进程信息等仍然保持相互隔离,两个容器的进程可以通过lo网卡进行通信。
Container 模式特点:
- 使用参数 –-network container:名称或ID 指定
- 与宿主机网络空间隔离
- 空器间共享网络空间,直接使用对方的网络
- 第一个容器的网络可能是bridge,或none,或者host,而第二个容器模式依赖于第一个容器,它们共享网络
- 如果第一个容器停止,将导致无法创建第二个容器
- 第二个容器可以直接使用127.0.0.1访问第一个容器
- 适合频繁的容器间的网络通信
- 默认不支持端口映射,较少使用
[root@centos7 ~]#docker run -d --name wordpress \
> -v /data/wordpress:/var/www/html/wp-content \
> -p 80:80 --restart=always wordpress:php7.4-apache
[root@centos7 ~]#docker run --restart=always --name mysql \
> --network container:wordpress \
> -v /data/mysql:/var/lib/mysql \
> -e MYSQL_ROOT_PASSWORD=123456 \
> -e MYSQL_USER=wordpress \
> -e MYSQL_DATABASE=wordpress \
> -e MYSQL_PASSWORD=123456 \
> -d mysql:8.0.29-oracle
自定义网络模式
使用自定义网络模式,实现不同集群应用的独立网络管理,而互不影响,而且在网一个网络内,可以直接利用容器名相互访问,非常便利。
自定义网络内的容器可以直接通过容器名进行相互的访问,而无需使用 --link
创建自定义网络
格式:(默认为bridge模式)
docker network create -d <mode> --subnet <CIDR> --gateway <网关> <自定义网络名称>
[root@ubuntu ~]#docker network create -d bridge --subnet 172.27.0.0/16 --gateway 172.27.0.1 test-net
[root@ubuntu ~]#docker network ls
NETWORK ID NAME DRIVER SCOPE
cabde0b33c94 bridge bridge local
cb64aa83626c host host local
10619d45dcd4 none null local
c90dee3b7937 test-net bridge local
#查看网络详细信息
[root@ubuntu ~]#docker inspect test-net
利用自定义网络实现 Wordpress
[root@ubuntu ~]#docker network create -d bridge --subnet 172.27.0.0/16 --
gateway 172.27.0.1 bridge2
[root@ubuntu ~]#docker run -d -p 8080:80 --network bridge2 --name
wordpress2 -v /data/wordpress2:/var/www/html --restart=always wordpress:php7.4-
apache
[root@ubuntu ~]#docker run --network bridge2 -e MYSQL_ROOT_PASSWORD=123456 -
e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=123456 --
name mysql -d -v /data/mysql2:/var/lib/mysql --restart=always mysql:8.0.29-
oracle
docker-compose单机编排工具
docker-compose 是 docker 容器的一种单机编排服务,docker-compose 是一个管理多个容器的工具,比如: 可以解决容器之间的依赖关系,就像启动一个nginx 前端服务的时候会调用后端的 tomcat,那就得先启动tomcat,但是启动tomcat 容器还需要依赖数据库,那就还得先启动数据库,dockercompose 可以用来解决这样的嵌套依赖关系,并且可以替代docker命令对容器进行创建、启动和停止等手工的操作。
docker compose可以通过官网安装,或者直接使用docker内置的子命令来实现docker-compose
#离线安装
#docker-compose文件
docker-compose-linux-x86_64-v2.24.3
[root@ubuntu ~]#chmod +x /usr/local/bin/docker-compose
[root@ubuntu ~]#ldd /usr/local/bin/docker-compose
#出现docker-compose版本就算安装成功
[root@ubuntu ~]#docker-compose version
docker-compose version 2.24.3
#以下为命令选项,需要在docker-compose.yml|yaml 文件所在在目录里执行
config -q #查看当前配置,没有错误不输出任何信息
up #创建并启动容器
build #构建镜像
bundle #从当前docker compose 文件生成一个以<当前目录>为名称的json格式的Docker Bundle 备
份文件
create #创建服务
down #停止和删除所有容器、网络、镜像和卷
events #从容器接收实时事件,可以指定json 日志格式
exec #进入指定容器进行操作
help #显示帮助细信息
images #显示镜像信息
kill #强制终止运行中的容器
logs #查看容器的日志
pause #暂停服务
port #查看端口
ps #列出容器
pull #重新拉取镜像,镜像发生变化后,需要重新拉取镜像
push #上传镜像
restart #重启服务
rm #删除已经停止的服务
run #一次性运行容器
scale #设置指定服务运行的容器个数,新版已废弃
start #启动服务
stop #停止服务
top #显示容器运行状态
unpause #取消暂定
docker compose 文件格式
#docker compose 文件是一个yaml格式的文件,所以注意行首的缩进很严格
#默认docker-compose命令会调用当前目录下的docker-compose.yml的文件,因此一般执行dockercompose命令前先进入docker-compose.yml文件所在目录
[root@ubuntu ~]#mkdir /data/docker-compose
[root@ubuntu ~]#cd /data/docker-compose
[root@ubuntu docker-compose]#vim docker-compose.yml
[root@ubuntu docker-compose]#cat docker-compose.yml
version: '3'
services:
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
depends_on:
- redis
redis:
image: redis:alpine
#查看配置和格式检查
[root@ubuntu docker-compose]#docker-compose config
#初次启动容器(前台执行)
[root@ubuntu docker-compose]#docker-compose up
#初次启动容器(后台执行)
[root@ubuntu docker-compose]#docker-compose up -d
#关闭容器
[root@ubuntu docker-compose]#docker-compose kill
#后续启动容器
[root@ubuntu docker-compose]#docker-compose start
#重启容器
[root@ubuntu docker-compose]#docker-compose restart
#停止容器
[root@ubuntu docker-compose]#docker-compose stop
#只删除停止的容器
[root@ubuntu docker-compose]#docker-compose rm
#停止并删除容器及镜像
[root@ubuntu docker-compose]#docker-compose down
注意:必须要在docker compose文件所在的目录执行
docker compose 启动多个容器
[root@ubuntu docker-compose]#cat docker-compose.yml
service-nginx-web:
image: 192.168.93.200/example/nginx-centos7-base:1.6.1
container_name: nginx-web
volumes:
#指定数据卷,将宿主机/data/nginx挂载到容器/apps/nginx/html
- /data/nginx:/apps/nginx/html/
expose:
- 80
- 443
ports:
- "80:80"
- "443:443"
service-tomcat-app1:
image: 192.168.93.200/example/tomcat-web:app1
container_name: tomcat-app1
expose:
- 8080
ports:
- "8081:8080"
service-tomcat-app2:
image: 192.168.93.200/example/tomcat-web:app2
container_name: tomcat-app2
expose:
- 8080
ports:
- "8082:8080"
实现 Wordpress 应用
#准备相关配置文件
[root@ubuntu ~]#mkdir -p wordpress/nginx
[root@ubuntu ~]#cd wordpress
[root@ubuntu wordpress]#vim nginx/wordpress.conf
server {
listen 80;
server_name wordpress.wang.org;
root /var/www/html;
index index.php;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
root /var/www/html;
fastcgi_index index.php;
fastcgi_pass wordpress:9000; #指定wordpress的名称
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
[root@ubuntu wordpress]#vim docker-compose.yaml
version: '3.3'
services:
mysql:
image: mysql:8.0.29-oracle
# ports:
# - '3306:3306'
volumes:
- ./mysql:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=123456
restart: always
wordpress:
image: wordpress:6.1-php8.0-fpm
# ports:
# - '9000:9000'
volumes:
- ./wordpress:/var/www/html
environment:
- WORDPRESS_DB_HOST=mysql
- WORDPRESS_DB_NAME=wordpress
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=123456
restart: always
nginx:
image: nginx:1.24.0
ports:
- '80:80'
volumes:
- ./nginx:/etc/nginx/conf.d
- ./wordpress:/var/www/html
restart: always
#提前拉取镜像
[root@ubuntu wordpress]#docker-compose pull
[root@ubuntu wordpress]#docker-compose images
#运行
[root@ubuntu wordpress]#docker-compose up
一键生成 Docker Compose
https://www.composerize.com/
搭建harbor私有仓库
harbor服务器:
192.168.93.200
192.168.93.201
客户端(用户):
192.168.93.100
192.168.93.101
Docker仓库,类似于yum仓库,是用来保存镜像的仓库。为了方便的管理和使用docker镜像,可以将镜像集中保存至Docker仓库中,将制作好的镜像push到仓库集中保存,在需要镜像时,从仓库中pull镜像即可。Docker 仓库分为公有云仓库和私有云仓库。
安装 Harbor
下载地址: https://github.com/vmware/harbor/releases
安装文档:
https://github.com/goharbor/harbor/blob/master/docs/install-config/_index.md
https://goharbor.io/docs/2.10.0/install-config/
下载harbor
#docker compose 必须先于harbor安装
#安装docker compose
#通过pip安装
[root@ubuntu ~]#apt -y install python-pip
[root@ubuntu ~]#pip install docker-compose
#下载Harbor安装包并解压缩
#先从github官网下载好安装包
[root@ubuntu ~]#wget
https://github.com/goharbor/harbor/releases/download/v2.7.1/harbor-offlineinstaller-v2.7.1.tgz
[root@ubuntu ~]#mkdir /apps
[root@ubuntu ~]#tar xvf harbor-offline-installer-v1.7.6.tgz -C /apps/
harbor 配置文件修改
[root@ubuntu~]#mv /apps/harbor/harbor.yml.tmpl /apps/harbor/harbor.yml
[root@ubuntu ~]#vim /apps/harbor/harbor.yml
hostname = 10.0.0.101 #修改此行,指向当前主机IP 或 FQDN,建议配置IP
harbor_admin_password = 123456 #修改此行指定harbor登录用户admin的密码,默认用户/密码:admin/Harbor12345
data_volume: /data/harbor #修改数据目录路径,使用大容量的高速磁盘,默认为/data
#如果不使用https,还需要将下面行注释掉
#https:
# port: 443
# certificate: /your/certificate/path
# private_key: /your/private/key/path
#可选项
ui_url_protocol = http #默认即可,如果修改为https,需要指定下面证书路径
ssl_cert = /data/cert/server.crt #默认即可,https时,需指定下面证书文件路径
ss_cert_key = /data/cert/server.key #默认即可,https时,需指定下面私钥文件路径
运行 harbor 安装脚本
#harbor默认占用80端口,安装前确保端口不冲突
#先安装python
[root@ubuntu~]#apt -y install python
#安装docker harbor (确保docker是启动状态)
[root@ubuntu~]#/apps/harbor/install.sh
#实现开机自动启动 harbor(旧版不会自启动)
[root@ubuntu~]#cat /etc/rc.local
#!/bin/bash
cd /apps/harbor
/usr/bin/docker-compose up
[root@ubuntu~]#chmod +x /etc/rc.local
单机harbor
harbor上必须先建立项目,才能上传镜像。
创建用户和项目授权
在项目内对用户授权,注意:至少是开发者以上才能上传镜像
命令行登录 Harbor
#启动harbor(如果harbor停止了)
[root@ubuntu ~]# docker compose start
#方法1
[root@ubuntu ~]#vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
--insecure-registry 192.168.93.200 --insecure-registry 192.168.93.201
#方法2
[root@ubuntu ~]#vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"],
"insecure-registries": ["192.168.93.200:80","192.168.93.201:80"] #说明: ":80"可省略
}
[root@ubuntu ~]#systemctl daemon-reload
[root@ubuntu ~]#systemctl restart docker
#非交互登录
[root@ubuntu ~]#docker login -u admin -p 123456 10.0.0.101
[root@ubuntu ~]#echo 123456 | docker login -u admin --password-stdin
192.168.93.200
#交互登录
[root@ubuntu1804 ~]#docker login 192.168.93.200
注意:如果登录失败,弹出https和443,可以在登录时加上80,如:192.168.93.200:80
给本地镜像打标签并上传到 Harbor
修改 images 的名称,不修改成指定格式无法将镜像上传到 harbor 仓库
格式:
Harbor主机IP/项目名/image名:版本
#上传镜像前,必须先登录harbor
[root@ubuntu ~]#docker login 192.168.93.200:80
#打标签
[root@localhost harbor]# docker tag nginx:1.24 192.168.93.200:80/test/nginx:1.24
#上传至harbor
[root@localhost harbor]# docker pull 192.168.93.200:80/test/nginx:1.24
下载 Harbor 的镜像
下载前必须修改docker的service 文件,加入harbor服务器的地址才可以下载
#方法1
[root@ubuntu ~]#vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
--insecure-registry 192.168.93.100 --insecure-registry 192.168.93.101
#方法2
[root@ubuntu ~]#vim/etc/docker/daemon.json
{
"insecure-registries": ["192.168.93.100", "192.168.93.101"]
}
[root@ubuntu ~]#systemctl daemon-reload
[root@ubuntu ~]#systemctl restart docker
#下载镜像
[root@centos7 ~]#docker pull 192.168.93.200:80/test/nginx:1.24
修改 Harbor 配置
后期如果修改harbor配置,比如: 修改IP地址等,可执行以下步骤生效
#停止docker compose
[root@ubuntu ~]#cd /apps/harbor/
[root@ubuntu harbor]#docker-compose stop
#修改harbor配置
[root@ubuntu harbor]#vim harbor.cfg
#更新配置
[root@ubuntu ~]#/apps/harbor/prepare
#重新启动docker compose
[root@ubuntu harbor]#docker-compose start