二、容器入门与实战

二、容器入门与实战

目录

1、容器

1.1 什么是容器?

容器是一种轻量级虚拟化,用于将应用程序和依赖的组件打包在一起,以便在不同的环境中进行移植和运行。

1.2 常用镜像仓库

1.3 为什么要用容器?

  • 真正的一次构建,到处运行
  • 更强的一致性
  • 可移植性极强
  • 提升资源利用率
  • 创建和启动速度快
  • 更细粒度的隔离性

2、Docker

2.1 什么是Docker?

Docker是一个开源的容器引擎,属于轻量级虚拟化。可以帮助技术人员将应用以及依赖项,打包到一个可移植的容器中,并可以轻松地发布到任何流行的Linux或Windows操作系统的机器上。

Docker通过提供容器化的应用运行环境,解决了环境管理复杂的问题,让应用的部署和运维变得更加简单和高效

2.2 Docker组件

  • Docker Client:Docker客户端,用于执行Docker的相关命令,比如镜像下载;
  • Docker Daemon:Docker守护进程,运行在服务器或者其他工作站上;
  • Docker Image:Docker镜像,相当于一个模板,可以用来启动容器;
  • Docker Container:Docker容器,由镜像启动,容器内运行着相关的应用程序;
  • Docker Registry:镜像仓库,用于存储和管理镜像的中央仓库。

2.3 Docker失宠,为什么还要用它?

  • Docker依旧是产品交付的最佳实践
  • Docker依旧是本地开发和测试的首选
  • Docker镜像和容器管理依旧最为灵活
  • Docker的普及和生态系统依旧无法替代
  • 对K8s有余悸的企业,依旧以Docker为主
  • 虽然K8s不再兼容Docker,镜像依旧可用
  • 还有很多其它的历史因素

2.4 配置docker

2.4.1 安装docker

# 下载docker镜像源
[root@docker ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 安装docker
[root@docker ~]# yum install docker-ce -y

# 设置开机自启动
[root@docker ~]# systemctl daemon-reload
[root@docker ~]# systemctl enable --now docker

2.4.2 配置镜像加速器

# 配置镜像加速器
[root@docker ~]# mkdir -p /etc/docker
[root@docker ~]# tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://docker.m.daocloud.io"],
"registry-mirrors": ["https://docker.xuanyuan.me"],
"registry-mirrors": ["https://docker.1ms.run"]
}
EOF

# 重新加载配置&重启服务
[root@docker ~]# systemctl daemon-reload
[root@docker ~]# systemctl restart docker

2.5 docker常用命令

2.5.1 查看 Docker 版本

[root@docker ~]# docker version
Client: Docker Engine - Community
 Version:           28.2.2
 API version:       1.50
 Go version:        go1.24.3
 Git commit:        e6534b4
 Built:             Fri May 30 12:09:15 2025
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          28.2.2
  API version:      1.50 (minimum version 1.24)
  Go version:       go1.24.3
  Git commit:       45873be
  Built:            Fri May 30 12:07:23 2025
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.7.27
  GitCommit:        05044ec0a9a75232cad458027ca83437aae3f4da
 runc:
  Version:          1.2.5
  GitCommit:        v1.2.5-0-g59923ef
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

2.5.2 查看 Docker 详细信息

[root@docker ~]# docker info
Client: Docker Engine - Community
 Version:    28.2.2
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.24.0
    Path:     /usr/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.36.2
    Path:     /usr/libexec/docker/cli-plugins/docker-compose
....

2.5.3 搜索镜像

[root@docker ~]# docker search nginx
NAME                                     DESCRIPTION                                     STARS     OFFICIAL
nginx                                    Official build of Nginx.                        20835     [OK]
nginx/nginx-ingress                      NGINX and  NGINX Plus Ingress Controllers fo…   107       
nginx/nginx-prometheus-exporter          NGINX Prometheus Exporter for NGINX and NGIN…   50 
....

2.5.4 拉取/下载镜像

# 拉取指定仓库里面的镜像:
[root@docker ~]# docker pull registry.cn-beijing.aliyuncs.com/dotbalo/counter:v1

# 拉取默认仓库的 Nginx 镜像:
# 把公网上的镜像拉取到本地服务器,不指定版本号为 latest
[root@docker ~]# docker pull nginx

# 拉取指定版本
[root@docker ~]# docker pull nginx:1.15

2.5.5 查看本地镜像

[root@docker ~]# docker images
REPOSITORY                                         TAG       IMAGE ID       CREATED         SIZE
nginx                                              latest    be69f2940aaf   6 weeks ago     192MB
registry.cn-beijing.aliyuncs.com/dotbalo/counter   v1        fc15e4dfb2b4   12 months ago   41MB
nginx                                              1.15      53f3fd8007f7   6 years ago     109MB

2.5.6 更改镜像 tag

[root@docker ~]# docker tag registry.cn-beijing.aliyuncs.com/dotbalo/counter:v1 registry.cn-beijing.aliyuncs.com/dotbalo/counter:v2

[root@docker ~]# docker images|grep registry.cn-beijing.aliyuncs.com/dotbalo/counter
registry.cn-beijing.aliyuncs.com/dotbalo/counter   v1        fc15e4dfb2b4   12 months ago   41MB
registry.cn-beijing.aliyuncs.com/dotbalo/counter   v2        fc15e4dfb2b4   12 months ago   41MB

2.5.7 删除镜像

# 指定id删除
[root@docker ~]# docker rmi be69f2940aaf
# 或者指定镜像名称删除
[root@docker ~]# docker rmi registry.cn-beijing.aliyuncs.com/dotbalo/counter:v2

[root@docker ~]# docker images
REPOSITORY                                         TAG       IMAGE ID       CREATED         SIZE
registry.cn-beijing.aliyuncs.com/dotbalo/counter   v1        fc15e4dfb2b4   12 months ago   41MB
nginx                                              1.15      53f3fd8007f7   6 years ago     109MB

2.5.8 导出导入

# 将镜像导出:
[root@docker ~]# docker save nginx:1.15 > nginx.tar
[root@docker ~]# ll
total 110412
-rw-r--r-- 1 root root 113060864 Jun  3 17:59 nginx.tar

# 为测试将这个镜像删除
[root@docker ~]# docker rmi 53f3fd8007f7

[root@docker ~]# docker images
REPOSITORY                                         TAG       IMAGE ID       CREATED         SIZE
registry.cn-beijing.aliyuncs.com/dotbalo/counter   v1        fc15e4dfb2b4   12 months ago   41MB

# 将镜像导入:
[root@docker ~]# docker load < nginx.tar 

[root@docker ~]# docker images|grep nginx
nginx                                              1.15      53f3fd8007f7   6 years ago     109MB

2.5.9 启动容器

# 使用 run -ti 前台启动一个容器:
[root@docker ~]# docker run -it nginx bash 

# 也可以使用-ti --rm参数,表示前台启动的容器退出后即删除

# 如果一个镜像需要一直运行,可以使用-d 进行后台启动:
[root@docker ~]# docker run -itd nginx bash

# 如果容器异常自动重启,也可以使用--restart=always
[root@docker ~]# docker run --restart=always -itd nginx bash

# 指定容器名称
[root@docker ~]# docker run --restart=always --name web01 -itd nginx bash

2.5.10 查看当前正在运行的容器

# 查看当前正在运行的容器
[root@docker ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED              STATUS              PORTS     NAMES
058fd2ef6e91   nginx     "/docker-entrypoint.…"   5 seconds ago        Up 4 seconds        80/tcp    web01
35438b4d48b5   nginx     "/docker-entrypoint.…"   About a minute ago   Up About a minute   80/tcp    infallible_proskuriakova
802c34ab7b0d   nginx     "/docker-entrypoint.…"   2 minutes ago        Up 2 minutes        80/tcp    pedantic_jang

# 查看所有容器,包括已经退出的:
[root@docker ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                     PORTS     NAMES
058fd2ef6e91   nginx     "/docker-entrypoint.…"   17 seconds ago   Up 17 seconds              80/tcp    web01
35438b4d48b5   nginx     "/docker-entrypoint.…"   2 minutes ago    Up 2 minutes               80/tcp    infallible_proskuriakova
802c34ab7b0d   nginx     "/docker-entrypoint.…"   3 minutes ago    Up 3 minutes               80/tcp    pedantic_jang
9848508c8104   nginx     "/docker-entrypoint.…"   4 minutes ago    Exited (0) 3 minutes ago             gifted_margulis

# 查看正在运行的容器(即显示出容器的 ID)
[root@docker ~]# docker ps -q
058fd2ef6e91
35438b4d48b5
802c34ab7b0d

# 查看所有容器的 ID,包括已经退出的
[root@docker ~]# docker ps -qa
058fd2ef6e91
35438b4d48b5
802c34ab7b0d
9848508c8104

2.5.11 查看容器运行信息

[root@docker ~]# docker inspect web01 | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.4",
                    "IPAddress": "172.17.0.4",

2.5.12 查看日志

# 查看容器的实时日志(10行)
[root@docker ~]# docker logs -f web01 --tail 10

2.5.13 进入一个容器

[root@docker ~]# docker exec -it web01 bash
root@058fd2ef6e91:/# 

2.5.14 端口映射

# 将容器里nginx的80端口映射成宿主机的88端口
[root@docker ~]# docker run -itd --name web02 -p 88:80 nginx 
bbba8d2332e39bbc94e5bbe5562a95e98b90d26dfa2fcb77349eb2c0b805148c

# 访问测试
[root@docker ~]# curl 127.0.0.1:88
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

2.5.15 停止容器

[root@docker ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                 NAMES
bbba8d2332e3   nginx     "/docker-entrypoint.…"   3 minutes ago    Up 3 minutes    0.0.0.0:88->80/tcp, [::]:88->80/tcp   web02
058fd2ef6e91   nginx     "/docker-entrypoint.…"   13 minutes ago   Up 13 minutes   80/tcp                                web01
35438b4d48b5   nginx     "/docker-entrypoint.…"   15 minutes ago   Up 15 minutes   80/tcp                                infallible_proskuriakova
802c34ab7b0d   nginx     "/docker-entrypoint.…"   16 minutes ago   Up 16 minutes   80/tcp                                pedantic_jang

# 通过容器名称停止一个正在运行的容器
[root@docker ~]# docker stop web01
web01

# 通过id停止一个正在运行的容器
[root@docker ~]# docker stop bbba8d2332e3
bbba8d2332e3

# 批量停止所有正在运行的容器
[root@docker ~]# docker stop `docker ps -q`
35438b4d48b5
802c34ab7b0d

2.5.16 删除容器

# 通过容器名称删除正在停止的容器
[root@docker ~]# docker rm web01
web01

# 通过id删除正在停止的容器
[root@docker ~]# docker rm bbba8d2332e3
bbba8d2332e3

# 批量删除正在停止的容器
[root@docker ~]# docker rm `docker ps -qa`
35438b4d48b5
802c34ab7b0d
9848508c8104

2.5.17 挂载文件和文件夹

# 挂载文件到容器
# 把宿主机的/tmp/test文件挂载到容器的/tmp/test文件
[root@docker ~]# docker run -itd --name web01 -v /tmp/test:/tmp/test nginx bash

# 测试往文件里追加数据
[root@docker ~]# echo "123" > /tmp/test 
[root@docker ~]# cat /tmp/test
123

# 进入容器内检查数据已同步
[root@docker ~]# docker exec -it web01 bash
root@32bffcb82bfb:/# cat /tmp/test
123

# 测试往文件里追加数据
root@32bffcb82bfb:/# echo "abc" > /tmp/test
root@32bffcb82bfb:/# cat /tmp/test
123
abc
root@32bffcb82bfb:/# exit
exit

# 退出容器检查发现数据已经同步
[root@docker ~]# cat /tmp/test
123
abc
# 挂载目录到容器:
# 把宿主机的/mnt目录挂载到容器的/mnt目录
[root@docker ~]# docker run -itd --name web02 -v /mnt:/mnt nginx bash

# 往测试目录里追加文件
[root@docker ~]# echo "ceshi" > /mnt/abc
[root@docker ~]# ll /mnt/
total 4
-rw-r--r-- 1 root root 6 Jun  3 18:36 abc

# 进入容器内检查数据已同步
[root@docker ~]# docker exec -it web02 bash
root@7c487e681218:/# ls /mnt/
abc
root@7c487e681218:/# cat /mnt/abc 
ceshi

# 测试往文件里追加数据
root@7c487e681218:/# echo "123" >> /mnt/abc 
root@7c487e681218:/# exit
exit

# 退出容器检查发现数据已经同步
[root@docker ~]# cat /mnt/abc 
ceshi
123

2.5.18 文件拷贝

# 将本机的文件拷贝到容器
[root@docker ~]# docker cp nginx.tar web02:/tmp

[root@docker ~]# docker exec web02 ls /tmp
nginx.tar

# 将容器的内部文件拷贝到宿主机
[root@docker ~]# docker cp web02:/mnt/abc ./

[root@docker ~]# ls
abc  nginx.tar

3、Dockerfile

3.1 什么是Dockerfile?

Dockerfile是一个文本文件,用于定义Docker镜像的构建步骤和过程。这个文件由一系列指令组成,每个指令都代表一个构建步骤。通过编写Dockerfile,用户可以定制化容器镜像,确保应用程序能够在容器中正确运行。

3.2 镜像制作

  • 先去找到一个基础的镜像 jre
  • 配置系统的源为国内的源
  • 创建用户并分配权限
  • 安装基础环境 – 直接换成具有该环境的基础镜像
    • Jdk
    • Python
    • PHP
  • Jar 启动

3.3 Dockerfile 的常用命令汇总

  • FROM:继承基础镜像
  • MAINTAINER:镜像制作作者的信息,将被弃用,使用LABEL替代
  • LABEL:k=v形式,将一些元数据添加至镜像
  • RUN:用来执行shell命令
  • EXPOSE:暴露端口号
  • CMD:启动容器默认执行的命令,会被覆盖
  • ENTRYPOINT:启动容器真正执行的命令,可以被覆盖
  • ENV:配置环境变量
  • ADD:复制文件到容器,一般拷贝文件,压缩包自动解压
  • COPY:复制文件到容器,一般拷贝目录
  • WORKDIR:设置容器的工作目录
  • USER:容器使用的用户
  • ARG:设置编译镜像时传入的参数

3.3.1 创建用户

# 创建dockerfile目录
[root@docker ~]# mkdir -p dockerfile
[root@docker ~]# cd dockerfile/

# 创建Dockerfile文件
[root@docker dockerfile]# vim Dockerfile
[root@docker dockerfile]# cat Dockerfile 
FROM centos:7
MAINTAINER Mr.yang
RUN useradd dot

# 执行构建
[root@docker dockerfile]# docker build -t centos:user .

# 检查构建好的镜像
[root@docker dockerfile]# docker images|grep user
centos       user      269c1d02e0b8   13 seconds ago   204MB

# 检验镜像是否构建成功
[root@docker dockerfile]# docker run --rm -it 269c1d02e0b8 cat /etc/passwd|grep dot
dot:x:1000:1000::/home/dot:/bin/bash

3.3.2 查看镜像构建信息

[root@docker dockerfile]# docker history 269c1d02e0b8
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
269c1d02e0b8   6 minutes ago   RUN /bin/sh -c useradd dot # buildkit           360kB     buildkit.dockerfile.v0
<missing>      6 minutes ago   MAINTAINER Mr.yang                              0B        buildkit.dockerfile.v0
<missing>      3 years ago     /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
<missing>      3 years ago     /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B        
<missing>      3 years ago     /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4…   204MB

3.3.3 添加环境变量

# 创建Dockerfile文件
[root@docker dockerfile]# vim Dockerfile 
[root@docker dockerfile]# cat Dockerfile 
FROM centos:7
MAINTAINER Mr.yang
RUN useradd dot
ENV envir=test version=v1.0
CMD echo "envir:$envir version:$version"

# 执行构建
[root@docker dockerfile]# docker build -t centos:env .

# 检查构建好的镜像
[root@docker dockerfile]# docker images|grep env
centos       env      269c1d02e0b8   17 minutes ago   204MB

# # 启动镜像验证 ENV和 CMD
[root@docker dockerfile]# docker run --rm -it b9e9b0373abb
envir:test version:v1.0

3.3.4 LABEL 和 MAINTAINER

# Dockerfile 使用 MAINTAINER 定义作者信息,但是这个参数将来会被弃用,可以使用 LABEL 进行替换

# 创建Dockerfile文件
[root@docker dockerfile]# vim Dockerfile 
[root@docker dockerfile]# cat Dockerfile 
FROM centos:7
# MAINTAINER Mr.yang #即将废弃
LABEL maintainer="Mr.yang" version="v1.0" multiple="true"
RUN useradd dot
ENV envir=test version=v1.0
CMD echo "envir:$envir version:$version"

# 执行构建
[root@docker dockerfile]# docker build -t centos:label .

# 检查构建好的镜像
[root@docker dockerfile]# docker images|grep label
centos       label     ed1b9c1c1daa   31 minutes ago   204MB

# 检验镜像是否构建成功
[root@docker dockerfile]# docker inspect ed1b9c1c1daa | grep Labels -A 15
            "Labels": {
                "maintainer": "Mr.yang",
                "multiple": "true",
                "org.label-schema.build-date": "20201113",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS",
                "org.opencontainers.image.created": "2020-11-13 00:00:00+00:00",
                "org.opencontainers.image.licenses": "GPL-2.0-only",
                "org.opencontainers.image.title": "CentOS Base Image",
                "org.opencontainers.image.vendor": "CentOS",
                "version": "v1.0"
            },
            "ArgsEscaped": true
        },

3.3.5 ADD 和 COPY

# 使用 ADD 添加一个压缩包,使用 WORKDIR 改变工作目录
[root@docker dockerfile]# vim Dockerfile 
[root@docker dockerfile]# cat Dockerfile 
FROM nginx
LABEL maintainer="Mr.yang"
ADD ./index.tar.gz /usr/share/nginx/html/
WORKDIR /usr/share/nginx/html

# 执行构建
[root@docker dockerfile]# docker build -t nginx:add .

# 检查构建好的镜像
[root@docker dockerfile]# docker images|grep add
nginx        add       773f75204cd4   18 minutes ago      192MB

# 检验镜像是否构建成功
# 工作目录已配置成功,tar包文件也已经放到指定目录(解压状态)
[root@docker dockerfile]# docker run --rm -it 773f75204cd4 bash
root@6f7194e124c5:/usr/share/nginx/html# ls
50x.html  index.html  index.html_add
# 使用 COPY 拷贝指定目录下的所有文件到容器,不包括本级目录。
# 此时只会拷贝 mnt 下的所有文件,不会将 mnt 文件夹拷贝过去
[root@docker dockerfile]# ls mnt/
abc

# 创建Dockerfile文件
[root@docker dockerfile]# vim Dockerfile 
[root@docker dockerfile]# cat Dockerfile 
FROM nginx
LABEL maintainer="Mr.yang"
ADD ./index.tar.gz /usr/share/nginx/html/
WORKDIR /usr/share/nginx/html
COPY mnt/ .

# 执行构建
[root@docker dockerfile]# docker build -t nginx:copy .

# 检查构建好的镜像
[root@docker dockerfile]# docker images|grep copy
nginx        copy      c5be46763bf2   9 minutes ago       192MB

# 检验镜像是否构建成功
[root@docker dockerfile]# docker run --rm -it c5be46763bf2 bash
root@055999536c45:/usr/share/nginx/html# ls
50x.html  abc  index.html  index.html_add

3.3.6 更改文件权限

[root@docker dockerfile]# vim Dockerfile 
[root@docker dockerfile]# cat Dockerfile 
FROM nginx
LABEL maintainer="Mr.yang"
WORKDIR /tmp
COPY --chown=nginx:group mnt/1.txt .
COPY --chmod=700 mnt/2.txt .
COPY --chown=nginx:group --chmod=700 mnt/3.txt .

# 执行构建
[root@docker dockerfile]# docker build -t nginx:chown .

# 检查构建好的镜像
[root@docker dockerfile]# docker images|grep chown
nginx        chown     9cfb73a1ff26   3 seconds ago       192MB

# 检验镜像是否构建成功
[root@docker dockerfile]# docker run --rm -it 9cfb73a1ff26 bash
root@3815d71437f0:/tmp# ls -l
total 0
-rw-r--r-- 1 nginx nginx 0 Jun  3 14:44 1.txt
-rwx------ 1 root  root  0 Jun  3 14:44 2.txt
-rwx------ 1 nginx nginx 0 Jun  3 14:44 3.txt

# 也可以复制目录并设置权限和所有者
# COPY --chown=nginx:group --chmod=700 mnt/ .

3.3.7 更改启动用户

# 创建Dockerfile文件
[root@docker dockerfile]# vim Dockerfile 
[root@docker dockerfile]# cat Dockerfile 
FROM centos:7
LABEL maintainer="Mr.yang"
RUN useradd -m tomcat -u 1001
USER 1001
WORKDIR /home/tomcat

# 执行构建
[root@docker dockerfile]# docker build -t centos:user2 .

# 检查构建好的镜像
[root@docker dockerfile]# docker images|grep user2
centos       user2     9f0bd6ddb5d9   9 seconds ago    204MB

# 检验镜像是否构建成功
[root@docker dockerfile]# docker run --rm -it 9f0bd6ddb5d9 bash
[tomcat@8fc7ed4ee381 ~]$ whoami
tomcat
[tomcat@8fc7ed4ee381 ~]$ touch 1
[tomcat@8fc7ed4ee381 ~]$ ls -l
total 0
-rw-rw-r-- 1 tomcat tomcat 0 Jun  3 15:11 1

3.3.8 ENTRYPOINT

# 创建Dockerfile文件
[root@docker dockerfile]# vim Dockerfile 
[root@docker dockerfile]# cat Dockerfile 
FROM centos:7
LABEL maintainer="Mr.yang"
RUN useradd dot
RUN mkdir -p dot
ENV envir=test version=v1.0
ENTRYPOINT echo "envir:$envir version:$version"

# 执行构建
[root@docker dockerfile]# docker build -t centos:entrypoint . 

# 检查构建好的镜像
[root@docker dockerfile]# docker images|grep entrypoint
centos       entrypoint   da7f326b960e   14 seconds ago      204MB

# 检验镜像是否构建成功
[root@docker dockerfile]# docker run --rm -it da7f326b960e
envir:test version:v1.0

3.3.9 CMD 和 ENTRYPOINT 区别

# CMD 可以被覆盖:
[root@docker dockerfile]# docker run --rm -it b9e9b0373abb ls /tmp
ks-script-DrRL8A  yum.log

# ENTRYPOINT 指定的不能被直接覆盖:
[root@docker dockerfile]# docker run --rm -it da7f326b960e ls /tmp
envir:test version:v1.0

# ENTRYPOINT 指定--entrypoint 参数,比如指定 entrypoint 为ls,后置命令为/tmp,就相当于ENTRYPOINT 是 ls,CMD 是/tmp
[root@docker dockerfile]# docker run --rm -it --entrypoint ls da7f326b960e /tmp
ks-script-DrRL8A  yum.log

3.3.10 Dockerfile 传参-动态构建

# 创建Dockerfile文件
[root@docker dockerfile]# vim Dockerfile 
[root@docker dockerfile]# cat Dockerfile 
FROM centos:7
LABEL maintainer="Mr.yang"
ARG USERNAME
ARG DIR="defaultValue"
RUN useradd -m $USERNAME -u 1001 && mkdir $DIR

# 执行构建
[root@docker dockerfile]# docker build --build-arg USERNAME="dot" -t centos:arg .

# 检查构建好的镜像
[root@docker dockerfile]# docker images|grep arg
centos       arg          bbcf9dc19358   27 seconds ago      204MB

# 检验镜像是否构建成功
[root@docker dockerfile]# docker run --rm -it bbcf9dc19358 cat /etc/passwd|grep dot
dot:x:1001:1001::/home/dot:/bin/bash

[root@docker dockerfile]# docker run --rm -it bbcf9dc19358 ls -ld defaultValue
drwxr-xr-x 2 root root 6 Jun  3 15:47 defaultValue

3.4 镜像优化

3.4.1 基础镜像体积

[root@docker dockerfile]# docker images|grep -w user
centos       user         269c1d02e0b8   3 hours ago         204MB

# 那这 204MB 是怎么来的呢?首先看一下创建用户的 Dockerfile:
[root@docker dockerfile]# cat Dockerfile 
FROM centos:7
MAINTAINER Mr.yang
RUN useradd dot

# 再来看一下执行 docker build 生成镜像时控制台的日志:
[root@docker dockerfile]# docker history 269c1d02e0b8
IMAGE          CREATED       CREATED BY                                      SIZE      COMMENT
269c1d02e0b8   3 hours ago   RUN /bin/sh -c useradd dot # buildkit           360kB     buildkit.dockerfile.v0
<missing>      3 hours ago   MAINTAINER Mr.yang                              0B        buildkit.dockerfile.v0
<missing>      3 years ago   /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
<missing>      3 years ago   /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B        
<missing>      3 years ago   /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4…   204MB  

# 所以要选择合适的镜像

3.4.2 使用 Alpine 作为基础镜像

# 将之前创建用户的 Dockerfile 改为 Alpine 镜像
# 创建Dockerfile文件
[root@docker dockerfile]# vim Dockerfile 
[root@docker dockerfile]# cat Dockerfile 
FROM alpine:3.20
LABEL maintainer="Mr.yang"
RUN adduser -D dot

# 执行构建
[root@docker dockerfile]# docker build -t alpine:user .

# 检查构建好的镜像(这样镜像体积就小了很多)
[root@docker dockerfile]# docker images|grep alpine
alpine       user         4563fc27227e   19 seconds ago      7.81MB
alpine       3.20         ff221270b9fb   3 months ago        7.8MB

3.4.3 多阶段构建

# 创建 Go 语言 Hello World 程序:
[root@docker dockerfile]# vim hw.go
[root@docker dockerfile]# cat hw.go 
package main
import "fmt"
func main() {
     fmt.Println("Hello World!")
}
# 单阶段构建:
# 创建Dockerfile文件
[root@docker dockerfile]# vim Dockerfile 
[root@docker dockerfile]# cat Dockerfile 
FROM golang:1.22.4-alpine3.20
LABEL maintainer="Mr.yang"
WORKDIR /opt
COPY hw.go /opt
RUN go build /opt/hw.go
CMD "./hw"

# 执行构建
[root@docker dockerfile]# docker build -t go:hw .

# 查看此时由一个阶段构建的镜像大小为260MB
[root@docker dockerfile]# docker images|grep hw
go           hw                  72d36d466568   14 seconds ago      260MB

# 但是上述的代码我们只需要构建步骤产生的二进制文件 hw 即可,这个文件大小可以进入到容器内部看一下
[root@docker dockerfile]# docker run --rm -it 72d36d466568 du -sh ./hw
1.8M	./hw
# 多阶段 Dockerfile 构建:
# 创建Dockerfile文件
[root@docker dockerfile]# vim Dockerfile 
[root@docker dockerfile]# cat Dockerfile 
FROM golang:1.22.4-alpine3.20 AS builder
LABEL maintainer="Mr.yang"
WORKDIR /opt
COPY hw.go /opt
RUN go build /opt/hw.go

FROM alpine:3.20
COPY --from=builder /opt/hw .
CMD "./hw"

# 执行构建
[root@docker dockerfile]# docker build -t alpine:hw2 .

# 查看此时由一个阶段构建的镜像大小为9.7MB
[root@docker dockerfile]# docker images|grep hw2
alpine       hw2                 c29dc5bfc1f5   16 seconds ago      9.7MB

# 检验镜像是否构建成功
[root@docker dockerfile]# docker run --rm -it c29dc5bfc1f5
Hello World!

3.5 综合练习

下载代码→构建→制作镜像→部署

3.5.1 制作 Vue/H5 前端镜像

# 下载代码
[root@docker dockerfile]# git clone https://gitee.com/dukuan/vue-project.git

# 创建Dockerfile文件
[root@docker dockerfile]# vim Dockerfile 
[root@docker dockerfile]# cat Dockerfile 
FROM node:lts AS builder
LABEL maintainer="Mr.yang"
WORKDIR /mnt
COPY vue-project/ .
RUN npm install --registry=https://registry.npmmirror.com/
RUN npm run build 

FROM nginx
WORKDIR /usr/shart/nginx/html/
COPY --from=builder /mnt/dist .

# 执行构建
[root@docker dockerfile]# docker build -t vue:v1 .

# 检验镜像是否构建成功
[root@docker dockerfile]# docker run --rm -it vue:v1 bash
root@63310814dc67:/usr/shart/nginx/html# ls
index.html  static

3.5.2 制作 golang 后端镜像

# 下载代码
[root@docker dockerfile]# git clone https://gitee.com/dukuan/go-project.git

# 创建Dockerfile文件
[root@docker dockerfile]# vim Dockerfile
[root@docker dockerfile]# cat Dockerfile
FROM golang:1.15 AS builder
LABEL maintainer="Mr.yang"
WORKDIR /mnt
COPY go-project/ .
ENV GO111MODULE=on
RUN go env -w GOPROXY=https://goproxy.cn,direct
RUN go build

FROM registry.cn-beijing.aliyuncs.com/dotbalo/alpine-glibc:alpine-3.9
COPY --from=builder /mnt/conf/ ./conf
COPY --from=builder /mnt/go-project ./
ENTRYPOINT [ "./go-project"]

# 执行构建
[root@docker dockerfile]# docker build -t go:v1 .

# 检验镜像是否构建成功
[root@docker dockerfile]# docker run -itd -p 8088:8080 go:v1 bash

image.png-174kB

4、镜像仓库

4.1 阿里云镜像仓库

官网:https://cr.console.aliyun.com/

image.png-244.4kB

4.1.1 创建命名空间

使用阿里云镜像仓库第一步需要创建命名空间,相当于 repository
image.png-40.7kB

image.png-18.5kB

4.1.2 镜像仓库登录

[root@harbor ~]# docker login crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com
Username: ywb1108
Password: 

WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/

Login Succeeded

4.1.3 推送本地镜像到远程仓库

# 修改tag
[root@harbor ~]# docker tag cf3ff089bd54 crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/alpine-glibc:alpine-3.9

# 推送其他仓库的镜像到阿里云仓库:
[root@harbor ~]# docker push crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/alpine-glibc:alpine-3.9

image.png-23.8kB

image.png-23.4kB

4.2 Harbor 私有仓库

4.2.1 配置docker-compose

# 设置软连接
[root@harbor ~]# ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/local/bin/

[root@harbor ~]# docker-compose -v
Dcurl -L https://github.com/docker C/compose version v2.36.2

# 批量停止harbor实例
docker-compose down
# 批量启动harbor实例
docker-compose up -d

4.2.2 安装 Harbor

# 下载到本地
[root@harbor ~]# wget https://github.com/goharbor/harbor/releases/download/v2.13.1/harbor-offline-installer-v2.13.1.tgz

# 解压tar包
[root@harbor ~]# tar xf harbor-offline-installer-v2.13.1.tgz 
[root@harbor ~]# cd harbor

# 加载配置
[root@harbor harbor]# docker load -i harbor.v2.13.1.tar.gz 

# 修改 Harbor 默认配置文件
[root@harbor harbor]# cp harbor.yml.tmpl harbor.yml
[root@harbor harbor]# vim harbor.yml

[root@harbor harbor]# sed -n "5p;10p;13,18p;47p;66p" harbor.yml
hostname: 192.168.200.53 
  port: 80
# https:
  # https port for harbor, default is 443
  # port: 443
  # The path of cert and key files for nginx
  # certificate: /your/certificate/path
  # private_key: /your/private/key/path
harbor_admin_password: Harbor12345
data_volume: /data/harbor

# hostname:Harbor 的访问地址,可以是域名或者 IP,生产推荐使用域名,并且带有证
书
# https:域名证书的配置,生产环境需要配置权威证书供 Harbor 使用,否则需要添加
insecure-registry 配置,由于是学习环境,所以本示例未配置证书
# harbor_admin_password:默认密码
data_volume:Harbor 的数据目录
# 创建 Harbor 数据目录并进行预配置:
[root@harbor harbor]# mkdir /data/harbor -p

# 加载配置启动
[root@harbor harbor]# ./prepare

# 执行安装:
[root@harbor harbor]# ./install.sh
# 如果配置不是https 协议,所有的Kubernetes 节点的Docker (如果是containerd 作为Runtime,可以参考下文配置 insecure-registry)都需要添加 insecure-registries 配置
[root@harbor harbor]# vim /etc/docker/daemon.json
[root@harbor harbor]# cat /etc/docker/daemon.json 
{
"registry-mirrors": ["https://docker.m.daocloud.io"],
"registry-mirrors": ["https://docker.xuanyuan.me"],
"registry-mirrors": ["https://docker.1ms.run"],
"insecure-registries": ["192.168.200.53"]
}
[root@harbor harbor]# systemctl daemon-reload
[root@harbor harbor]# systemctl restart docker

# 登陆测试
[root@harbor harbor]# docker login 192.168.200.53
Username: admin
Password: 

WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/

Login Succeeded

# 修改tag名称
[root@harbor harbor]# docker tag cf3ff089bd54 192.168.200.53/library/alpine-glibc:alpine-3.9

# 测试上传镜像
[root@harbor harbor]# docker push 192.168.200.53/library/alpine-glibc:alpine-3.9

web界面访问

image.png-187.5kB

image.png-32.1kB

image.png-70.6kB

4.2.3 多用户权限管理

1.创建一个测试用的私有仓库

image.png-202368.9kB

image.png-40.5kB

2.创建一个测试用户

image.png-33.2kB

image.png-32kB

3.将该用户分配到该项目

image.png-343.8kB

image.png-193.7kB

4.使用taobao用户上传一个镜像

# 退出之前用户的登陆,使用taobao用户登陆
[root@harbor harbor]# docker logout

[root@harbor harbor]# docker login 192.168.200.53
Username: taobao
Password:

# 修改tag名称
[root@harbor harbor]# docker tag cf3ff089bd54 192.168.200.53/taobao/alpine-glibc:alpine-3.9

# 测试上传镜像
[root@harbor harbor]# docker push 192.168.200.53/taobao/alpine-glibc:alpine-3.9

5.使用taobao用户登陆web界面
只能看见公开仓库已经有权限的私有仓库

image.png-43.8kB

上传成功

image.png-62.9kB

4.2.4 仓库镜像清理和垃圾回收

1.每一个仓库下配置清理的策略

image.png-54.3kB

image.png-85.9kB

天级不适合,会有多天未变更的情况。所以选择个数

image.png-79kB

image.png-47.9kB

2.配置垃圾清理定时任务

image.png-89.8kB

image.png-62.2kB

也可以手动执行

image.png-84.5kB

3.配置日志清理定时任务

image.png-42.6kB

注意⚠️:垃圾清理&日志清理定时任务多了一个秒

image.png-151.8kB

4.2.5 仓库镜像复制管理

1.设置固定密码

image.png-104.5kB

2.新建目标

image.png-58.3kB

image.png-73.7kB

3.测试连接成功之后创建

image.png-50.7kB

image.png-36.7kB

4.创建复制的规则

image.png-54.1kB

image.png-50kB

image.png-23.1kB

5.复制

image.png-26.6kB

6.查看结果

image.png-41.1kB

image.png-30.8kB

5、Containerd必知必会

5.1 容器运行时接口-CRI

CRI(Container Runtime Interface)是Kubernetes中用于实现容器运行时和Kubernetes之间交互的标准化接口。CRI定义了Kubernetes与底层容器运行时的通信协议和接口规范,可以让Kubernetes与不同的容器运行时进行交互,实现跨容器运行时的一致性,以达到在不需要改动任何代码的情况下支持多种运行时,比如Containerd、CRI-O、Kata等。

5.2 Containerd

5.2.1 什么是Containerd?

  • Containerd是一种容器运行时,可以管理容器的整个生命周期,包含镜像的传输、容器的运行和销毁、容器的监控,同时也可以管理更底层的存储和网络等。
  • Containerd属于Docker引擎中的一部分,在2016年12月从Docker Engine中剥离,成为了一个可以独立使用的容器运行时(Runtime),并且在2017年捐赠给了CNCF,成为了CNCF的顶级项目之一。
  • Containerd是一个开源的容器运行时项目,同时也是CNCF体系中已经毕业的容器运行时。

5.2.2 Containerd和Docker的关系

Docker包含Containerd,但Containerd并不完全依赖于Docker。Docker是一个完整的容器化平台,提供了镜像构建、容器管理、网络管理、存储管理等功能。而Containerd只是作为Docker的一个组件,负责容器的生命周期管理

image.png-536.3kB

5.2.3 Docker和Containerd调用链

image.png-795kB

5.2.4 Containerd客户端工具介绍

  • ctr:Containerd原生客户端工具
  • nerdctl:为K8s设计,遵循CRI接口规
  • crictl:用于Containerd并且友好兼容DockerCli使用习惯
# 下载工具:
[root@k8s-master01 ~]# wget https://github.com/containerd/nerdctl/releases/download/v1.7.6/nerdctl-1.7.6-linux-amd64.tar.gz

# 安装:
[root@k8s-master01 ~]# tar xf nerdctl-1.7.6-linux-amd64.tar.gz
[root@k8s-master01 ~]# mv nerdctl /usr/local/bin/

命令对比(我们一般都是使用nerdctl)

image.png-175.7kB

5.3 Containerd配置insecure registry

# 修改配置(所有k8s节点都要执行)
[root@k8s-master01 ~]# vim /etc/containerd/config.toml
[root@k8s-master01 ~]# sed -n "170,172p" /etc/containerd/config.toml 
      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
      		[plugins."io.containerd.grpc.v1.cri".registry.mirrors."192.168.200.53"]
			endpoint = ["http://192.168.200.53"]

# 重启服务
[root@k8s-master01 ~]# systemctl restart containerd

# 需要把K8s所有的节点都需要进行更改
# config.toml并不是直接给ctr命令去使用的
# docker拉取的镜像和containerd没有任何关系
# 测试连接
[root@k8s-master01 ~]# kubectl create deploy test-harbor --image=192.168.200.53/library/counter:v1
deployment.apps/test-harbor created


[root@k8s-master01 ~]# kubectl get po
NAME                           READY   STATUS    RESTARTS      AGE
...
test-harbor-7946964f55-2c5fs   1/1     Running   0             3s

5.4 Containerd命名空间管理

Containerd的Namespace是一个强大的工具,主要用于实现容器之间的资源隔离、访问控制和安全性。可以实现多个容器在同一台主机上独立运行而不会相互干扰,从而提高了系统的可扩展性和可管理性。

Containerd的命令空间和Kubernetes的命令空间是两个不同的概念!

# 使用str查看命令空间
[root@k8s-master01 ~]# ctr ns ls
NAME   LABELS 
k8s.io        

# 使用str创建一个空间
[root@k8s-master01 ~]# ctr ns c test
[root@k8s-master01 ~]# ctr ns ls
NAME   LABELS 
k8s.io        
test          

# 打个标签
[root@k8s-master01 ~]# ctr ns label test a=b
[root@k8s-master01 ~]# ctr ns ls
NAME   LABELS 
k8s.io        
test   a=b   

# 使用str删除一个命名空间
[root@k8s-master01 ~]# ctr ns rm test
test
[root@k8s-master01 ~]# ctr ns ls
NAME   LABELS 
k8s.io 

5.5 Containerd镜像管理

5.5.1 下载一个镜像

# 下载一个镜像
[root@k8s-master01 ~]# ctr i pull 192.168.200.53/library/counter:v1 --plain-http

# 查看default下面有什么镜像(下载镜像时如果不指定命名空间会默认下载到default下面)
[root@k8s-master01 ~]# ctr -n default i ls
REF                               TYPE                                                 DIGEST                                                                  SIZE     PLATFORMS   LABELS 
192.168.200.53/library/counter:v1 application/vnd.docker.distribution.manifest.v2+json sha256:dad22fecd8043fb4178d4cf9252c938cda16dbc898ea00ba2c0808407a28a607 16.0 MiB linux/amd64 - 

5.5.2 修改tag

# 修改tag
[root@k8s-master01 ~]# ctr i tag 192.168.200.53/library/counter:v1 crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/counter:v1

[root@k8s-master01 ~]# ctr i ls
REF                                                                        TYPE                                                 DIGEST                                                                  SIZE     PLATFORMS   LABELS 
192.168.200.53/library/counter:v1                                          application/vnd.docker.distribution.manifest.v2+json sha256:dad22fecd8043fb4178d4cf9252c938cda16dbc898ea00ba2c0808407a28a607 16.0 MiB linux/amd64 -      
crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/counter:v1 application/vnd.docker.distribution.manifest.v2+json sha256:dad22fecd8043fb4178d4cf9252c938cda16dbc898ea00ba2c0808407a28a607 16.0 MiB linux/amd64 - 

5.5.3 上传一个镜像

# 上传一个镜像(推送到阿里云仓库,需要指定用户名输入密码)
[root@k8s-master01 ~]# ctr i push crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/counter:v1 --user ywb1108
Password: 

image.png-43.6kB

5.5.4 删除一个镜像

# 删除一个镜像
[root@k8s-master01 ~]# ctr i rm crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/counter:v1

[root@k8s-master01 ~]# ctr i ls
REF                               TYPE                                                 DIGEST                                                                  SIZE     PLATFORMS   LABELS 
192.168.200.53/library/counter:v1 application/vnd.docker.distribution.manifest.v2+json sha256:dad22fecd8043fb4178d4cf9252c938cda16dbc898ea00ba2c0808407a28a607 16.0 MiB linux/amd64 - 

5.5.5 导入与导出

# 导出
[root@k8s-master01 ~]# ctr i export ./counter:v1.tar 192.168.200.53/library/counter:v1

[root@k8s-master01 ~]# ls -d counter:v1.tar
counter:v1.tar
# 创建一个新的命名空间
[root@k8s-master01 ~]# ctr ns c counter

# 导入指定的命名空间
[root@k8s-master01 ~]# ctr -n counter i import counter:v1.tar 

[root@k8s-master01 ~]# ctr -n counter i ls
REF                               TYPE                                                 DIGEST                                                                  SIZE     PLATFORMS   LABELS 
192.168.200.53/library/counter:v1 application/vnd.docker.distribution.manifest.v2+json sha256:dad22fecd8043fb4178d4cf9252c938cda16dbc898ea00ba2c0808407a28a607 16.0 MiB linux/amd64 - 

5.5.6 挂载

# 挂载到/mnt目录下
[root@k8s-master01 ~]# ctr i mount 192.168.200.53/library/counter:v1 /mnt/

[root@k8s-master01 ~]# ls /mnt/
bin  docker-entrypoint.d   etc   lib    mnt  proc  run   srv  tmp  var
dev  docker-entrypoint.sh  home  media  opt  root  sbin  sys  usr

# 直接指定挂载目录卸载
[root@k8s-master01 ~]# ctr i unmount /mnt/

[root@k8s-master01 ~]# ls /mnt/
[root@k8s-master01 ~]#

5.6 Containerd容器管理

# 查看一个命名空间下有多少实例
[root@k8s-master01 ~]# ctr -n k8s.io c ls

# 创建一个实例
[root@k8s-master01 ~]# ctr c create 192.168.200.53/library/counter:v1 counter 
 
[root@k8s-master01 ~]# ctr c ls
CONTAINER    IMAGE                                RUNTIME                  
counter      192.168.200.53/library/counter:v1    io.containerd.runc.v2 

# 查看当前运行信息
[root@k8s-master01 ~]# ctr c info counter

# 删除一个实例
[root@k8s-master01 ~]# ctr c rm counter

此博客来源于:https://edu.51cto.com/lecturer/11062970.html