二、容器入门与实战
二、容器入门与实战
1、容器
1.1 什么是容器?
容器是一种轻量级虚拟化,用于将应用程序和依赖的组件打包在一起,以便在不同的环境中进行移植和运行。
1.2 常用镜像仓库
- Harbor:https://goharbor.io/
- 阿里云:https://cr.console.aliyun.com/
- Docker官方:https://hub.docker.com/
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

4、镜像仓库
4.1 阿里云镜像仓库
官网:https://cr.console.aliyun.com/

4.1.1 创建命名空间
使用阿里云镜像仓库第一步需要创建命名空间,相当于 repository


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


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



4.2.3 多用户权限管理
1.创建一个测试用的私有仓库


2.创建一个测试用户


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


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界面
只能看见公开仓库已经有权限的私有仓库

上传成功

4.2.4 仓库镜像清理和垃圾回收
1.每一个仓库下配置清理的策略


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


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


也可以手动执行

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

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

4.2.5 仓库镜像复制管理
1.设置固定密码

2.新建目标


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


4.创建复制的规则



5.复制

6.查看结果


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的一个组件,负责容器的生命周期管理

5.2.3 Docker和Containerd调用链

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)

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:

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

浙公网安备 33010602011771号