docker

目录

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

posted @ 2024-12-12 19:26  三两螺蛳粉  阅读(24)  评论(0编辑  收藏  举报