1.1 Docker简介
Docker之父Solomon Hykes:Docker就好比传统的货运集装箱
2008 年LXC(LinuX Contiainer)发布,但是没有行业标准,兼容性非常差
docker2013年首次发布,由Docker, Inc开发
1.1.1什么是Docker
Docker是管理容器的引擎,为应用打包、部署平台,而非单纯的虚拟化技术
它具有以下几个重要特点和优势:
-  轻量级虚拟化 :Docker 容器相较于传统的虚拟机更加轻量和高效,能够快速启动和停止,节省系统资源。 -  例如,启动一个 Docker 容器可能只需要几秒钟,而启动一个虚拟机则可能需要几分钟。 
 
-  
-  一致性 :确保应用程序在不同的环境中(如开发、测试、生产)具有一致的运行表现。 -  无论在本地还是云端,应用的运行环境都能保持相同,减少了因环境差异导致的问题。 
 
-  
-  可移植性 :可以轻松地将 Docker 容器从一个平台迁移到另一个平台,无需担心依赖和环境配置的差异。 -  比如,在本地开发的容器可以无缝部署到云服务器上。 
 
-  
-  高效的资源利用:多个 Docker 容器可以共享主机的操作系统内核,从而更有效地利用系统资源。 
-  易于部署和扩展:能够快速部署新的应用实例,并且可以根据需求轻松地进行水平扩展。 
总之,Docker 极大地简化了应用程序的开发、部署和管理流程,提高了开发效率和运维的便利性。它在现代软件开发和云计算领域得到了广泛的应用。

1.1.2 docker在企业中的应用场景
-  在企业中docker作为业务的最小载体而被广泛应用 
-  通过docker企业可以更效率的部署应用并更节省资源 
[!NOTE]
IaaS(Infrastructure as a Service),即基础设施即服务
PaaS是(Platform as a Service)即指平台即服务
SaaS(Software as a Service)软件运营服务是

1.1.3 docker与虚拟化的对比

| 虚拟机 | docker容器 | |
|---|---|---|
| 操作系统 | 宿主机上运行虚拟机OS | 共享宿主机OS | 
| 存储 | 镜像较大(GB | 镜像小(MB) | 
| 性能 | 操作系统额外的cpu、内存消耗 | 几乎无性能损耗 | 
| 移植性 | 笨重、与虚拟化技术耦合度高 | 轻量、灵活迁移 | 
| 隔离性 | 完全隔离 | 安全隔离 | 
| 部署 | 慢、分钟级 | 快速、秒级 | 
| 运行密度 | 一般几十个 | 单机支持上千容器 | 
1.1.4 docker的优势
-  对于开发人员:Build once、Run anywhere。 
-  对于运维人员:Configure once、Run anything 
-  容器技术大大提升了IT人员的幸福指数! 
2 部署docker
官方站点:https://docs.docker.com/
2.2.1 配置软件仓库
cd /etc/yum.repos.d
 ]# vim docker.repo
 [docker]
 name=docker-ce
 baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/stable
 gpgcheck=0
2.2.2 安装docker-ce并启动服务
#安装docker
 ]# yum install -y docker-ce 
#编辑docker启动文件,设定其使用iptables的网络设定方式,默认使用nftables
 [root@docker ~]# vim /usr/lib/systemd/system/docker.service
 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true
]# systemctl  enable --now docker
 ]# docker info
2.2.3 激活内核网络选项
#在rhel7中 需要
 ]# vim /etc/sysctl.d/docker.conf
 net.bridge.bridge-nf-call-iptables = 1
 net.bridge.bridge-nf-call-ip6tables = 1
 net.ipv4.ip_forward = 1
]# sysctl --system
 ]# systemctl  restart docker
二 Docker的基本操作
2.1 Docker镜像管理
2.1.1 搜索镜像
[root@Docker-node1 ~]# docker search nginx
NAME           DESCRIPTION                                      STARS     OFFICIAL
 nginx          Official build of Nginx.                         20094     [OK]
 @@@省略内容
| 参数 | 说明 | 
|---|---|
| NAME | 镜像名称 | 
| DESCRIPTION | 镜像说明 | 
| STARS | 点赞数量 | 
| OFFICIAL | 是否是官方的 | 
2.1.2 拉取镜像
#从镜像仓库中拉取镜像
 [root@Docker-node1 ~]# docker pull busybox
 [root@Docker-node1 ~]# docker pull nginx:1.26-alpine
#查看本地镜像
 [root@Docker-node1 ~]# docker images
 REPOSITORY                        TAG           IMAGE ID       CREATED         SIZE
 nginx                             latest        900dca2a61f5   7 weeks ago     188MB
 nginx                             1.26-alpine   b32ed582bddb   7 weeks ago     43.2MB
 ubuntu                            latest        35a88802559d   2 months ago    78.1MB
 busybox                           latest        65ad0d468eb1   15 months ago   4.26MB
 centos                            7             eeb6ee3f44bd   2 years ago     204MB
 centos                            latest        5d0da3dc9764   2 years ago     231MB
 gcr.io/distroless/base-debian12   latest        7273f3276b21   N/A             20.7MB
 gcr.io/distroless/base-debian11   latest        2a6de77407bf   N/A             20.6MB
2.1.3 查看镜像信息
[root@Docker-node1 ~]# docker image inspect nginx:1.26-alpine
2.1.4 导出镜像
#保存镜像
 [root@Docker-node1 ~]# docker image save nginx:latest -o nginx-latest.tar.gz
 [root@Docker-node1 ~]# docker image save nginx:latest nginx:1.26-alpine -o nginx.tag.gz
#保存所有镜像    
 [root@Docker-node1 ~]# docker save  `docker images | awk 'NR>1{print $1":"$2}'` -o images.tar.gz
[!NOTE]
-  -o:指定导出镜像的位置; 
-  可以同时导出多个镜像到一个文件中; 
-  指定.tar.gz 可以导出并压缩。 
2.1.5 删除镜像
[root@Docker-node1 ~]# docker rmi nginx:latest
[root@Docker-node1 ~]# docker rmi `docker images | awk 'NR>1{print $1":"$2}'`
2.2 容器的常用操作
2.2.1 启动容器
[root@Docker-node1 ~]# docker run  -d --name mario -p 80:8080 timinglee/mario
 [root@Docker-node1 ~]# docker run -it --name centos7 centos:7
 [root@3ba22e59734f /]#    #进入到容器中,按<ctrl>+<d>退出并停止容器,#按<ctrl>+<pq>退出但不停止容器
#重新进入容器
 [root@docker ~]# docker attach centos7
 [root@3ba22e59734f /]#
#在容器中执行命令
 [root@docker ~]# docker exec -it  test ifconfig
 lo        Link encap:Local Loopback
           inet addr:127.0.0.1  Mask:255.0.0.0
           inet6 addr: ::1/128 Scope:Host
           UP LOOPBACK RUNNING  MTU:65536  Metric:1
           RX packets:0 errors:0 dropped:0 overruns:0 frame:0
           TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
           collisions:0 txqueuelen:1000
           RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
-d            #后台运行
 -i            #交互式运行
 -t            #打开一个终端
 --name        #指定容器名称
 -p            #端口映射 -p 80:8080    把容器8080端口映射到本机80端口
 --rm        #容器停止自动删除容器
 --network     #指定容器使用的网络
2.2.2 查看容器运行信息
root@Docker-node1 ~]# docker ps                    #查看当前运行容器
 [root@Docker-node1 ~]# docker ps -a                    #查看所有容器
 [root@Docker-node1 ~]# docker inspect busybox        #查看容器运行的详细信息
root@Docker-node1 ~]# docker stop busybox            #停止容器
 [root@Docker-node1 ~]# docker kill busybox            #杀死容器,可以使用信号
 [root@Docker-node1 ~]# docker start busybox            #开启停止的容器
[!NOTE]
容器内的第一个进程必须一直处于运行的状态,否则这个容器,就会处于退出状态!
2.2.4 删除容器
[root@Docker-node1 ~]# docker rm centos7 #删除停止的容器
[root@Docker-node1 ~]# docker rm -f busybox #删除运行的容器
[root@Docker-node1 ~]# docker container prune -f #删除所有停止的容器
2.2.5 容器内容提交
默认情况下,容器被删除后,在容器中的所有操作都会被清理,包括要保存的文件
如果想永久保存,那么我们需要把动作提交,提交后会生成新的镜像
当我们在运行新镜像后即可看到我们提交的内容
[root@Docker-node1 ~]# docker run -it --name test busybox
 / # touch leefile                                            #在容器中建立文件
 / # ls
 bin      etc      leefile  lib64    root     tmp      var
 dev      home     lib      proc     sys      usr
 / #
 [root@Docker-node1 ~]# docker rm test    #删掉容器后    
 test
 [root@Docker-node1 ~]# docker run -it --name test busybox    #删掉容器后开启新的容器文件不存在    
 / # ls
 bin    dev    etc    home   lib    lib64  proc   root   sys    tmp    usr    var
 / #
[root@Docker-node1 ~]# docker commit -m "add leefile" test  busybox:v1
 sha256:c8ff62b7480c951635acb6064acdfeb25282bd0c19cbffee0e51f3902cbfa4bd
 [root@Docker-node1 ~]# docker images
 REPOSITORY                        TAG           IMAGE ID       CREATED          SIZE
 busybox                           v1            c8ff62b7480c   12 seconds ago   4.26MB
[root@Docker-node1 ~]# docker image history busybox:v1
 IMAGE          CREATED         CREATED BY                          SIZE      COMMENT
 c8ff62b7480c   2 minutes ago   sh                                  17B       add leefile
 65ad0d468eb1   15 months ago   BusyBox 1.36.1 (glibc), Debian 12   4.26MB
2.2.6 系统中的文件和容器中的文件传输
[root@Docker-node1 ~]# docker cp  test2:/leefile /mnt        #把容器中的文件复制到本机
 Successfully copied 1.54kB to /mnt
 [root@Docker-node1 ~]# docker cp /etc/fstab  test2:/fstab    #把本机文件复制到容器中
2.2.7 查询容器内部日志
三 docker镜像构建
3.1 docker镜像结构
-  共享宿主机的kernel 
-  base镜像提供的是最小的Linux发行版 
-  同一docker主机支持运行多种Linux发行版 
-  采用分层结构的最大好处是:共享资源 

3.2 镜像运行的基本原理
-  Copy-on-Write 可写容器层 
-  容器层以下所有镜像层都是只读的 
-  docker从上往下依次查找文件 
-  容器层保存镜像变化的部分,并不会对镜像本身进行任何修改 
-  一个镜像最多127层 

3.3 镜像获得方式
-  基本镜像通常由软件官方提供 
-  企业镜像可以用官方镜像+Dockerfile来生成 
-  系统关于镜像的获取动作有两种: -  docker pull 镜像地址 
-  docker load –i 本地镜像包 
 
-  
3.4 镜像构建
3.4.1 构建参数
| FROM | 指定base镜像 eg:FROM busybox:version | 
|---|---|
| COPY | 复制文件 eg:COPY file /file 或者 COPY [“file”,”/”] | 
| MAINTAINER | 指定作者信息,比如邮箱 eg:MAINTAINER user@example.com 在最新版的docker中用LABEL KEY="VALUE"代替 | 
| ADD | 功能和copy相似,指定压缩文件或url eg: ADD test.tar /mnt 或者 eg:ADD http://ip/test.tar /mnt | 
| ENV | 指定环境变量 eg:ENV FILENAME test | 
| EXPOSE | 暴漏容器端口 eg:EXPOSE 80 | 
| VOLUME | 申明数据卷,通常指数据挂载点 eg:VOLUME [“/var/www/html”] | 
| WORKDIR | 切换路径 eg:WORKDIR /mnt | 
| RUN | 在容器中运行的指令 eg: touch file | 
| CMD | 在启动容器时自动运行动作可以被覆盖 eg:CMD echo $FILENAME 会调用shell解析 eg:CMD [“/bin/sh”,”-c”,“echo $FILENAME”] 不调用shell解析 | 
| ENTRYPOINT | 和CMD功能和用法类似,但动作不可被覆盖 | 
#FROM COPY 和MAINTAINER
 [root@Docker-node1 ~]# mkdir  docker/
 [root@Docker-node1 ~]# cd docker/
 [root@Docker-node1 docker]# touch leefile
 [root@Docker-node1 docker]# vim Dockerfile 
 FROM busybox:latest                #指定使用的基础镜像
 MAINTAINER lee@timinglee.org    #指定作者信息
 COPY leefile /                    #复制当前目录文件到容器指定位置,leefile必须在当前目录中
[root@Docker-node1 docker]# docker build -t example:v1 . #构建镜像
四 docker 镜像仓库的管理
4.1 什么是docker仓库
Docker 仓库(Docker Registry) 是用于存储和分发 Docker 镜像的集中式存储库。
它就像是一个大型的镜像仓库,开发者可以将自己创建的 Docker 镜像推送到仓库中,也可以从仓库中拉取所需的镜像。
Docker 仓库可以分为公共仓库和私有仓库:
-  公共仓库,如 Docker Hub,任何人都可以访问和使用其中的镜像。许多常用的软件和应用都有在 Docker Hub 上提供的镜像,方便用户直接获取和使用。 -  例如,您想要部署一个 Nginx 服务器,就可以从 Docker Hub 上拉取 Nginx 的镜像。 
 
-  
-  私有仓库则是由组织或个人自己搭建和管理的,用于存储内部使用的、不希望公开的镜像。 -  比如,一家企业为其特定的业务应用创建了定制化的镜像,并将其存储在自己的私有仓库中,以保证安全性和控制访问权限。 
 
-  
通过 Docker 仓库,开发者能够方便地共享和复用镜像,加速应用的开发和部署过程。
4.2 docker hub
Docker Hub 是 Docker 官方提供的一个公共的镜像仓库服务。
它是 Docker 生态系统中最知名和广泛使用的镜像仓库之一,拥有大量的官方和社区贡献的镜像。
以下是 Docker Hub 的一些关键特点和优势:
-  丰富的镜像资源:涵盖了各种常见的操作系统、编程语言运行时、数据库、Web 服务器等众多应用的镜像。 -  例如,您可以轻松找到 Ubuntu、CentOS 等操作系统的镜像,以及 MySQL、Redis 等数据库的镜像。 
 
-  
-  官方支持:提供了由 Docker 官方维护的一些重要镜像,确保其质量和安全性。 
-  社区贡献:开发者们可以自由上传和分享他们创建的镜像,促进了知识和资源的共享。 
-  版本管理:对于每个镜像,通常都有多个版本可供选择,方便用户根据需求获取特定版本。 
-  便于搜索:用户可以通过关键词轻松搜索到所需的镜像。 
4.2.1 docker hub的使用方法
#登陆官方仓库
 [root@docker ~]# docker login
Username: timinglee
 Password:
 WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
 Configure a credential helper to remove this warning. See
 https://docs.docker.com/engine/reference/commandline/login/#credential-stores
 Login Succeeded
登录完成
#登陆信息保存位置
 [root@docker ~]# cd .docker/
 [root@docker .docker]# ls
 config.json
 [root@docker .docker]# cat config.json
 {
         "auths": {
                 "https://index.docker.io/v1/": {
                         "auth": "dGltaW5nbGVlOjY3NTE1MTVtaW5nemxu"(登录交互的密钥)
                 }
         }
将本地镜像上传到公共docker仓库
[root@docker ~]# docker push  timinglee/base-debian11:latest
 The push refers to repository [docker.io/timinglee/base-debian11]
 6835249f577a: Pushed
 24aacbf97031: Pushed
 8451c71f8c1e: Pushed
 2388d21e8e2b: Pushed
 c048279a7d9f: Pushed
 1a73b54f556b: Pushed
 2a92d6ac9e4f: Pushed
 bbb6cacb8c82: Pushed
 ac805962e479: Pushed
 af5aa97ebe6c: Pushed
 4d049f83d9cf: Pushed
 9ed498e122b2: Pushed
 577c8ee06f39: Pushed
 5342a2647e87: Pushed
 latest: digest: sha256:f8179c20f1f2b1168665003412197549bd4faab5ccc1b140c666f9b8aa958042 size: 3234
上传成功
4.3 docker仓库的工作原理
仓库中的三个角色
index docker索引服务,负责并维护有关用户帐户、镜像的校验以及公共命名空间的信息。
registry docker仓库,是镜像和图表的仓库,它不具有本地数据库以及不提供用户认证,通过Index Auth service的Token的方式进行认证
Registry Client Docker充当registry客户端来维护推送和拉取,以及客户端的授权。
4.3.1 pull原理
镜像拉取分为以下几步:
1.docker客户端向index发送镜像拉去请求并完成与index的认证
2.index发送认证token和镜像位置给dockerclient
3.dockerclient携带token和根据index指引的镜像位置取连接registry
4.Registry会根据client持有的token跟index核实身份合法性
5.index确认此token合法性
6.Registry会根据client的请求传递镜像到客户端
4.3.2 push原理

镜像上传的步骤:
1.client向index发送上传请求并完成用户认证
2.index会发方token给client来证明client的合法性
3.client携带index提供的token连接Registry
4.Registry向index合适token的合法性
5.index证实token的合法性
6.Registry开始接收客户端上传过来的镜像
4.4 docker私有仓库的建立
docker hub虽然方便,但是还是有限制
-  需要internet连接,速度慢 
-  所有人都可以访问 
-  由于安全原因企业不允许将镜像放到外网 
好消息是docker公司已经将registry开源,我们可以快速构建企业私有仓库
地址: https://docs.docker.com/registry/deploying/
搭建简单的registry仓库
1.下载registry镜像
[root@docker ~]# docker pull registry
 Using default tag: latest
 latest: Pulling from library/registry
 930bdd4d222e: Pull complete
 a15309931e05: Pull complete
 6263fb9c821f: Pull complete
 86c1d3af3872: Pull complete
 a37b1bf6a96f: Pull complete
 Digest: sha256:12120425f07de11a1b899e418d4b0ea174c8d4d572d45bdb640f93bc7ca06a3d
 Status: Downloaded newer image for registry:latest
 docker.io/library/registry:latest
2.开启registry
[root@docker ~]# docker run  -d -p 5000:5000 --restart=always --name registry registry
 bc58d3753a701ae67351fac335b06a4d7f66afa10ae60b992f647117827734c5
 [root@docker ~]# docker ps
 CONTAINER ID   IMAGE      COMMAND                   CREATED         STATUS         PORTS            NAMES
 bc58d3753a70   registry   "/entrypoint.sh /etc…"   7 seconds ago   Up 6 seconds   5000/tcp, 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry
3.上传镜像到仓库中
#给要上传的经镜像大标签
 [root@docker ~]# docker tag busybox:latest  172.25.254.100:5000/busybox:latest
#docker在上传的过程中默认使用https,但是我们并没有建立https认证需要的认证文件所以会报错
 [root@docker ~]# docker push 172.25.254.100:5000/busybox:latest
 The push refers to repository [172.25.254.100:5000/busybox]
 Get "https://172.25.254.100:5000/v2/": dial tcp 172.25.254.100:5000: connect: connection refused
 #配置非加密端口
 [root@docker ~]# vim /etc/docker/daemon.json
 {
   "insecure-registries" : ["http://172.25.254.100:5000"]
 }
[root@docker ~]# systemctl restart docker
#上传镜像
 [root@docker ~]# docker push  172.25.254.100:5000/busybox:latest
 The push refers to repository [172.25.254.100:5000/busybox]
 d51af96cf93e: Pushed
 latest: digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b size: 527
#查看镜像上传
 [root@docker ~]# curl 172.25.254.100:5000/v2/_catalog
 {"repositories":["busybox"]}
4.5docker私有仓库做加密认证(大体和https做加密过程一样)
加密之前要做解析
vim /etc/hosts
172.25.254.100 reg.timinglee.org #(仓库地址)
#生成认证key和证书
 [root@docker ~]#  openssl req -newkey  rsa:4096 \
 -nodes -sha256 -keyout certs/timinglee.org.key \
 -addext "subjectAltName = DNS:reg.timinglee.org" \        #指定备用名称
 -x509 -days 365 -out certs/timinglee.org.crt
You are about to be asked to enter information that will be incorporated
 into your certificate request.
 What you are about to enter is what is called a Distinguished Name or a DN.
 There are quite a few fields but you can leave some blank
 For some fields there will be a default value,
 If you enter '.', the field will be left blank.
 -----
 Country Name (2 letter code) [XX]:CN
 State or Province Name (full name) []:Shaanxi
 Locality Name (eg, city) [Default City]:Xi'an
 Organization Name (eg, company) [Default Company Ltd]:timinglee
 Organizational Unit Name (eg, section) []:docker
 Common Name (eg, your name or your server's hostname) []:reg.timinglee.org
 Email Address []:admin@timinglee.org
#启动registry仓库
 [root@docker ~]# docker run -d -p 443:443 --restart=always --name registry \
 > --name registry -v /opt/registry:/var/lib/registry \
 > -v /root/certs:/certs \
 > -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
 > -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/timinglee.org.crt \
 > -e REGISTRY_HTTP_TLS_KEY=/certs/timinglee.org.key registry
[root@docker docker]# docker push reg.timinglee.org/busybox:latest        #docker客户端没有key和证书
 Error response from daemon: Get "https://reg.timinglee.org/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority
#为客户端建立证书
 [root@docker docker]# mkdir /etc/docker/certs.d/reg.timinglee.org/ -p
 [root@docker docker]# cp /root/certs/timinglee.org.crt  /etc/docker/certs.d/reg.timinglee.org/ca.crt
 [root@docker docker]# systemctl restart docker
[root@docker docker]# docker push reg.timinglee.org/busybox:latest                                 The push refers to repository [reg.timinglee.org/busybox]
 d51af96cf93e: Pushed
 latest: digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b size: 527
 [root@docker docker]# curl  -k https://reg.timinglee.org/v2/_catalog
 {"repositories":["busybox"]}