Docker&Containerd使用总结
1、docker安装
CentOS中安装
# 配置yum源为aliyun mv CentOS-Base.repo CentOS-Base.repo.bak wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo # 使用aliyun的yum源安装docker vim /etc/yum.repos.d/docker.repo [docker] name=Docker Repository baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/$releasever/$basearch/stable/ gpgcheck=1 gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg enabled=1 # 重新生成yum缓存 yum clean all yum makecache # docker compose部署 yum -y install https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-compose-plugin-2.27.1-1.el7.x86_64.rpm yum -y install docker-ce docker-ce-cli containerd.io docker-compose-plugin docker-compose
wget --no-check-certificate https://download.docker.com/linux/centos/docker-ce.repo -P /etc/yum.repos.d/
yum list docker-ce --showduplicates | sort -r #查看可以安装的版本
yum install -y docker-ce-18.03.1.ce-1.el7.centos #或使用yum install -y docker-ce命令安装,不推荐
systemctl start dockerd.service # 启动docker服务
Ubuntu中安装
# 一键安装
apt-get install -y apt-transport-https ca-certificates curl software-properties-common && curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - && sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" && apt-get update && sudo apt-get install -y docker-ce
# 查看可安装的版本(中间列为docker版本号)
apt-cache madison docker-ce
# 安装指定版本
apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io
apt-get install docker-ce=5:20.10.9~3-0~ubuntu-bionic
# 启动docker服务
systemctl start dockerd.service
# 二进制方式安装docker需要安装iptables才能启动docker服务 apt install iptables
2、docker daemon.json文件常用配置
# data-root后边的值是Docker数据存储的目录。确保该目录存在且Docker进程有权限写入 # 主要关注data-root的值是大硬盘目录存放docker相关文件的目录 # insecure-registries后边的值是私有镜像仓库地址,多个私有镜像仓库地址配置格式为["仓库1","仓库2"] # registry-mirrors后边的值是配置Docker registry的镜像拉取镜像 # exec-opts部分针对于部署k8s做的预配置,可以减少容器日志保存大小及配合kubelet使用systemd # Docker版本或内核不支持overlay2.override_kernel_check选项导致docker服务启动失败时,删除该选项 # 使用:journalctl -u docker.service --since "5 minutes ago" 命令查看docker服务启动日志 mkdir -p /etc/docker /data/docker && cat > /etc/docker/daemon.json <<EOF { "insecure-registries": [ "10.2.41.191:5000" ], "registry-mirrors": [ "https://dockerproxy.com", "https://hub-mirror.c.163.com", "https://mirror.baidubce.com", "https://ccr.ccs.tencentyun.com" ], "proxies": { "http-proxy": "http://proxy.example.com:3128", "https-proxy": "https://proxy.example.com:3129", "no-proxy": "*.test.example.com,.example.org,127.0.0.0/8" }, "data-root": "/data/docker", "exec-opts": [ "native.cgroupdriver=systemd" ], "log-level": "info", "log-driver": "json-file", "log-opts": { "max-size": "20m", "max-file": "3" }, "storage-driver": "overlay2", "storage-opts": [ "overlay2.override_kernel_check=true" ] } EOF
3、docker镜像操作常用命令
# 登陆本地docker仓库 docker login -u[user] -p[password] localhost:8080 # 登出本地docker仓库 docker logout localhost:8080 # 打包系统(--exclude:排除指定目录,两条命令二选一,注意第二条命令后面有个点) tar -cvpf /tmp/centos6-base.tar --exclude=proc --exclude=sys --exclude=dev --exclude=run --exclude=boot / tar -cvpf /tmp/system.tar --directory=/ --exclude=proc --exclude=sys --exclude=dev --exclude=run --exclude=boot . # 导入打包好的系统(注意docker镜像名不能有大写字母) cat centos6-base.tar | docker import - centos6-base docker import centos6-base.tar centos6-base # 启动并进入容器,--rm:退出容器后自动删除容器,一般用于测试容器是否能正常运行 docker run -it --rm --name=alpine alpine:latest /bin/sh # -p:映射端口,--name:指定容器名称,-d:表示放到后台运行,--net:指定网络类型(bridge|host|none|container:NAME/ID|user_defined_network) docker run -p 8080:80 -p 162:162/udp --hostname=test --net=bridge --name=[NAMES] -it -d [REPOSITORY[:TAG]] /bin/bash # 提交一个运行中的容器为镜像(-p:在commit时,将容器暂停) docker commit -p [CONTAINER ID] [REPOSITORY[:TAG]] # 下载docker镜像,加[:TAG]下载指定版本的镜像(centos7-ansible:6.4),不加则下载最新的镜像 docker pull ansible/centos7-ansible # 查看本地的docker镜像 docker images # 将Docker镜像打包成tar归档文件 docker save -o /root/image.tar [REPOSITORY]:[TAG] # 将多个Docker镜像打包成一个tar归档文件 docker save -o images.tar image1:tag1 image2:tag2 image3:tag3 ... # 导入.tar归档文件 docker load </root/image.tar docker load -i /root/image.tar # 把.tar归档文件打包为.gz格式,-9,使用最高压缩率,-k,保留原文件 gzip -c image.tar >image.tar.gz gzip -9k image.tar # 解压.gz格式的镜像文件 gzip -d image.tar.gz gunzip -c image.tar.gz > image.tar # 直接导入.gz格式的镜像文件 gzip -dc image.tar.gz | docker load gunzip -c image.tar.gz | docker load # 把.tar归档文件打包为.xz格式,-k,保留原文件,-z,显式指定压缩模式 xz -c image.tar >image.tar.xz xz -T0 -zk image.tar # 解压.xz格式的镜像文件,-d,解压,-k,保留原文件,xzcat等价于xz -dc,-Tn,使用n个线程,-T0,让程序选择线程数(使用所有可用核心) xz -T0 -dk image.tar.xz xzcat -T0 -k image.tar.xz >image.tar # 直接导入.xz格式的镜像文件 xz -T0 -dc image.tar.xz | docker load xzcat -T0 image.tar.xz | docker load # 删除docker镜像 docker image rm -f [REPOSITORY]:[TAG] # 删除旧标签,此操作仅删除标签,不会删除镜像本身,若还有其他标签指向同一镜像则不会删除镜像数据 docker rmi oldname1:tag1 oldname2:tag2 # 在仓库中搜索docker镜像 docker search centos7 # 检查网络配置 docker network inspect bridge
4、docker容器操作常用命令
# 运行一个容器(-d:后台运行容器;--privileged:使container内的root拥有真正的root权限) docker container run -d --privileged -it [镜像名称] /sbin/init # 启动或停止容器 docker container start/stop [CONTAINER ID]/[NAMES] # 查看容器日志 docker logs [CONTAINER ID]/[NAMES] # 进入已启动的docker容器 docker exec -it [CONTAINER ID]/[NAMES] sh # 强制删除运行中的docker容器 docker container rm -f [CONTAINER ID]/[NAMES] # 查看所有docker容器,docker ps查看运行中的容器 docker ps -a # 修改容器名称 docker container rename [NAMES] [NEW_NAMES] # 查看docker默认配置文件目录 docker info | grep "Docker Root Dir" # 容器默认配置文件目录(489a4ec81e86前十二位为容器container id) cd /var/lib/docker/containers/489a4ec81e869cade7fb1bd887f51f72727606ea2602292f98e10fd2fb80985b/ # 查看多个容器运行状态 docker stats [NAMES] [NAMES] # 拷贝宿主机文件到容器 docker cp my.sh c3646071ecd2:/opt/my.sh # 拷贝容器中的文件到宿主机 docker cp c3646071ecd2:/opt/my.sh ./my.sh # 只清理未使用的容器 docker container prune # 只清理未使用的镜像 docker image prune -a # 只清理未使用的网络 docker network prune # 只清理未使用的卷 docker volume prune # 仅清理未使用的缓存条目(默认行为,保留当前正在使用的缓存,需要确认时不会删除正在使用的缓存) docker builder prune # 强制无提示清理(谨慎使用) docker builder prune -f # 仅保留最近1天的构建缓存 docker builder prune --filter "until=24h" -f # 查看将要删除的内容(预览模式) docker system prune --dry-run # 清理未使用的镜像、容器、网络、卷 docker system prune # 删除所有未使用的容器、镜像、网络和构建缓存 docker system prune -a # 强制删除,不提示确认 docker system prune -a -f
5、运行中的docker容器增加端口映射
iptables -A DOCKER ! -i docker0 -o docker0 -p tcp -s 0.0.0.0/0 -d 172.17.0.2 --dport 65510 -j ACCEPT
iptables -t nat -A DOCKER ! -i docker0 -p tcp --dport 65510-j DNAT --to-destination 172.17.0.2:65510
iptables -t nat -A POSTROUTING -p tcp --dport 65510 -j MASQUERADE
iptables -nvL
iptables -t nat -nvL
查看container端口映射(使用iptables开启的端口映射无法查看)
docker container port [CONTAINER] 80/tcp
docker port [CONTAINER] 80/tcp
6、docker的五种网络模式
--net=bridge|host|none|container:container_id/container_name|user_defined_network #指定容器网络模式;
--net=bridge #默认模式。为容器创建独立的网络命名空间,分配网卡、IP地址等网络配置,并通过veth接口对,将容器挂载到一个虚拟网桥(默认为docker0)上,类似于VMware的NAT模式;
--net=host #不为容器创建独立的网络命名空间,容器内看到的网络配置(网卡信息、路由表、Iptables规则等)均与主机上保持一致。注意其他资源还是与主机隔离的,类似于VMware的桥接模式;
--net=none #为容器创建独立的网络命名空间,但不进行网络配置,即容器内没有创建网卡、IP地址等;
--net=container:container_id/container_name #新创建的容器共享指定的已存在容器的网络命名空间,两个容器内的网络配置共享,但其他资源(进程空间、文件系统等)还是相互隔离的;
--net=user_defined_network #用户自行用network相关命令创建一个网络,同一个网络内的容器彼此可见,可以采用更多类型的网络插件。
默认的桥接网络:在默认情况下,Docker使用docker0桥接网络连接所有容器。不提供自动的名字解析功能。
用户定义的桥接网络:当使用用户定义的桥接网络时,Docker会在该网络上启动一个嵌入式的DNS服务器。这个DNS服务器负责监听来自同一网络中容器的DNS查询,并将服务名称转换成相应的IP地址。实现通过容器名访问容器
https://cloud.tencent.com/developer/article/1922478 # docker容器间通信
# 创建自定义网络并固定容器IP,注意自定义网络才能固定容器IP docker network create --driver=bridge --subnet=172.28.0.0/16 --gateway=172.28.0.1 customize_net docker run --name report-backend --net=customize_net -p 162:162/udp -p 8000:8000 --ip=172.28.0.2 -v /app/reports:/app/reports -d report-backend:latest docker run --name report-frontend -p 80:80 --net=customize_net --add-host=backend:172.28.0.2 --ip=172.28.0.3 -d report-frontend:latest # 使用--dns向容器中添加dns地址 docker run --name report-frontend-dns -p 80:80 --dns 8.8.8.8 --dns 114.114.114.114 -d report-frontend:latest # 查看当前Docker主机上的所有网络 docker network ls # 查看网络配置 docker network inspect customize_net
7、修改容器配置文件
docker container stop fb7c338a6c93
systemctl stop docker.service
cd /var/lib/docker/containers/fb7c338a6c934359aff9936e32ebb69bf46dd7f64e1e7892a7340367850e7e0b
vim hostconfig.json
vim config.v2.json
systemctl start docker.service
docker ps -a
docker container start fb7c338a6c93
注意:
修改容器配置文件前必需先停容器再停docker服务再修改容器配置文件,更改端口映射和网络模式,hostconfig.json文件和config.v2.json文件都需要修改。启动docker服务后使用docker ps -a命令查看不到修改完配置文件的容器时,请检查配置文件是否修改正确
8、创建容器启动脚本和健康检查脚本
[root@test /]# vim /bin/start.sh #进入容器里创建start.sh脚本,并给脚本添加可执行权限(chmod +x /bin/start.sh)
#!/bin/bash /etc/init.d/sshd start /bin/bash #保留一个终端,防止容器自动退出
# docker健康检查相关选项 docker run -d \ --name my-container \ --health-cmd="/check.sh" \ # 脚本必须在镜像里,脚本必须有可执行权限,脚本必须用exit 0 或exit 1 明确返回状态码,返回0 → Docker显示healthy,返回1 → Docker显示unhealthy --health-start-period=30s \ # 启动缓冲期:前30秒失败不计入不健康判定 --health-interval=10s \ # 检查间隔:每10秒执行一次健康检查 --health-retries=3 \ # 重试次数:连续失败3次才标记为unhealthy --health-timeout=5s \ # 超时时间:检查命令超过5秒没响应则视为失败(建议必加) [REPOSITORY[:TAG]] # 返回STATUS列:healthy(健康) / unhealthy(不健康) / starting(启动缓冲期中) docker inspect --format "{{.State.Health.Status}}" 容器名/ID
#!/bin/sh # 健康检查脚本示例(check.sh) # 检查 PostgreSQL 是否存活 if su - postgres -c "pg_isready -h localhost -p 5432 -q"; then # 获取主从状态,去除空白字符 cluster_status=$(su - postgres -c "psql -t -c 'select pg_is_in_recovery();'" 2>/dev/null | xargs) if [ "$cluster_status" = "t" ]; then # 从库:停止除 PostgreSQL 外所有服务 services=$(supervisorctl status | sed 's/\x1b\[[0-9;]*m//g' | grep -v 'postgresql' | awk '{print $1}' | xargs) if [ -n "$services" ]; then supervisorctl stop $services fi else # 主库:启动所有未运行服务 services=$(supervisorctl status | sed 's/\x1b\[[0-9;]*m//g' | grep -v 'Running' | awk '{print $1}' | xargs) if [ -n "$services" ]; then supervisorctl start $services fi fi # PG 就绪,脚本退出0 → 健康检查成功 exit 0 else # PG 未就绪,脚本退出1 → 健康检查失败 exit 1 fi
9、docker容器使用systemctl命令报错
root@nginx:~# systemctl
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
使用以下命令运行容器
docker run --cpus 2 -m 2g -p 22:22 -p 5000:5000 --add-host=nginx:192.168.1.2 --add-host=mysql:192.168.1.3 -v /sites:/var/www/html --restart=always --privileged --name flask --hostname centos8 --net=bridge -it -d centos8:1.0.0 /usr/sbin/init
参数说明:
--cpus 指定可以使用cpu的核数
-m 指定可以使用的内存大小
-p 指定映射端口
--add-host 添加hosts解析
-v 映射主机目录到容器目录
--privileged 使容器有root权限需要和/usr/sbin/init配合使用
--name 指定容器名称
--hostname 指定容器主机名
--net 指定网络类型
--restart=always "无条件重启"。无论容器如何停止(包括你手动docker stop),只要Docker守护进程启动运行,它就会尽力启动这个容器。它不区分容器停止的原因。 这通常用于你需要该容器持续运行,即使管理员手动停止后,也能在守护进程重启时自动恢复的场景(但需谨慎,这可能违背管理员意图)。
--restart=unless-stopped "除非已停止"。这是更常用且通常更符合预期的策略。容器因自身原因(进程退出)或Docker守护进程重启而停止时,它会自动重启。关键点:当且仅当容器是被用户使用docker stop命令明确停止时,Docker会记录这个"已停止"状态,并且以后(包括守护进程重启后)不再自动启动它。 这尊重了管理员的明确停止操作,是生产环境中实现高可用容器的推荐策略。
10、docker、ctr、crictl命令对比
| 命令 | docker | ctr(containerd),在k8s集群中使用ctr需要加上 -n k8s.io | crictl(kubernetes) |
| 查看运行的容器 | docker ps | ctr task ls/ctr container ls | crictl ps |
| 查看镜像 | docker images | ctr image ls # 在k8s集群中使用ctr命令查看镜像 ctr -n k8s.io image ls |
crictl images |
| 查看容器日志 | docker logs | 无 | crictl logs |
| 查看容器数据信息 | docker inspect | ctr container info [CONTAINER] | crictl inspect |
| 查看容器资源 | docker stats | ctr task metrics [TASK] (获取容器的内存、CPU和PID的限额与使用量) |
crictl stats |
| 启动/关闭已有容器 | docker start/stop | ctr task kill [TASK] (关闭) ctr task rm [TASK] (删除) ctr task start --log-uri /var/log/xxx.log -d [CONTAINER] (启动) |
crictl start/stop |
| 运行一个新的容器 | docker run | ctr run -d --rm --net-host --mount type=bind,src=[HOST_PATH],dst=[CONTAINER_PATH],options=rbind:rw --log-uri /var/log/xxx.log [IMAGE] [CONTAINER_NAME] -d后台运行,--mount指定宿主机目录挂载到容器目录,--log-uri指定容器日志文件路径(需要先创建xxx.log文件) |
无(最小单元为pod) |
| 修改镜像标签 | docker tag | ctr image tag # 在k8s集群中使用ctr修改镜像标签 ctr -n k8s.io images tag [源TAG] [修改后TAG] |
无 |
| 创建一个新的容器 | docker create | ctr container create | crictl create |
| 导入镜像 | docker load | ctr -n k8s.io images import image.tar # 在k8s集群中导入.gz和.xz格式镜像 gzip -dc image.tar.gz | ctr -n k8s.io images import - xz -T0 -dc image.tar.xz | ctr -n k8s.io images import - xzcat -T0 image.tar.xz | ctr -n k8s.io images import - |
无 |
| 导出镜像 | docker save | ctr image export <导出文件名> <镜像名> | 无 |
| 删除容器 | docker rm | ctr container rm | crictl rm |
| 删除镜像 | docker rmi | ctr image rm | crictl rmi |
| 拉取镜像 | docker pull | ctr image pull | ctictl pull |
| 推送镜像 | docker push | ctr image push # 在k8s集群中使用ctr命令推送镜像,-k:忽略证书 ctr -n k8s.io image push -k [IMAGE] |
无 |
| 进入容器内 | docker exec |
ctr task exec --exec-id 0 -t [TASK] sh |
crictl exec |
11、nerdctl工具操作Containerd
# k8s默认使用k8s.io,而nerdctl默认使用default namspace。如果需要查看k8s相关镜像需要加上"-n k8s.io"来指定 # 查看镜像 nerdctl -n k8s.io image ls # 导出镜像 nerdctl -n k8s.io image save registry.images.net/nginx:latest -o nginx_latest.tar # 导入镜像 nerdctl -n k8s.io image load -i nginx_latest.tar # 修改镜像tag nerdctl -n k8s.io tag registry.images.net/nginx:latest registry.cloud.net/nginx:latest # 上传镜像到仓库 nerdctl -n k8s.io image push registry.cloud.net/nginx:latest # 查看k8s集群中pod的CONTAINER ID nerdctl -n k8s.io ps # 进入pod nerdctl -n k8s.io exec -it [CONTAINER ID] -- sh # 登陆仓库 nerdctl login -u admin -p passw0rd registry.cloud.net # 登出仓库 nerdctl logout registry.cloud.net
12、使用dockerfile文件构建镜像
# 使用本地镜像作为基础镜像,先把镜像pull到本地,然后再使用dockfile文件打包镜像,本地没有则从镜像源pull # [root@localhost ~]# docker pull alpine # [root@localhost ~]# docker images # REPOSITORY TAG IMAGE ID CREATED SIZE # alpine latest aded1e1a5b37 3 weeks ago 7.83MB FROM alpine:latest # 设置工作目录 WORKDIR /app # 定义WEBSERVER变量,如果没有指定,默认为nginx,该变量可以在构建Docker镜像时通过--build-arg选项传递给Docker build # docker build --build-arg WEBSERVER=apache -t registry.docker.net/apache:1.0 . #ARG WEBSERVER=nginx # 在Dockerfile中使用Shell命令实现条件逻辑,每个RUN命令都会在Docker镜像中创建一个新层,这会增加镜像的大小。可以尝试使用&&连接符组合命令 #RUN if [ "$WEBSERVER" = "nginx" ]; then \ # apk update && apk install -y nginx; \ # elif [ "$WEBSERVER" = "apache" ]; then \ # apt-get update && apt-get install -y apache2; \ # else \ # echo "No valid webserver specified"; \ # fi # alpine镜像修改时区 #RUN apk add --no-cache tzdata \ # && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ # && echo "Asia/Shanghai" > /etc/timezone \ # && rm -rf /usr/share/zoneinfo/UTC || true # 清理tzdata的缓存信息(可选,减少镜像大小) # alpine镜像安装中文字体包,其它镜像中文字体包名:ttf-noto-cjk #RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \ # && apk update \ # && apk add --no-cache fontconfig ttf-dejavu freetype harfbuzz ca-certificates \ # && apk add --no-cache ttf-freefont font-noto-cjk \ # && fc-cache -fv # --no-cache-dir: 这个选项告诉pip不要缓存安装包,以减少镜像的体积。在Docker中,由于每个命令都会生成一个新的镜像层,如果不使用这个选项,pip会将下载的包缓存到镜像中,从而增加镜像的大小 #COPY requirements.txt . #RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \ # && apk add --no-cache python3 py3-pip \ # && pip install --no-cache-dir -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ # 安装Python依赖包 RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \ && apk add --no-cache curl python3 py3-pip \ && pip install --no-cache-dir --break-system-packages \ Flask \ gevent \ gevent-websocket \ Flask-SocketIO \ flask-sqlalchemy \ paramiko \ requests \ -i https://mirrors.aliyun.com/pypi/simple/ # 暴露Flask默认端口(按需修改) EXPOSE 5000 # 建议在运行时挂载代码,或在此处添加代码复制 COPY flask /app/flask # 设置默认启动命令(根据实际情况修改) CMD ["python", "./flask/flaskrun.py"] # -f dockerfile: 这个选项指定要使用的Dockerfile的文件名。默认情况下,Docker会查找名为Dockerfile的文件,但如果你将其命名为其他文件名(如 dockerfile),就需要使用此选项来指定。 # -t flask:1.0: 这个选项用于为创建的镜像指定一个名称和标签。在这里,镜像的名称是 flask,标签是 1.0,最终形成的完整镜像名为 flask:1.0。 # .: 这个点表示上下文目录。Docker客户端会将当前目录中的文件(及其子目录)作为构建上下文,Dockerfile 中的指令能使用这些文件。 # 使用dockerfile文件构建镜像命令 # [root@localhost ~]# docker build -t registry.docker.net/flask:1.0 -f dockerfile . # [root@localhost ~]# docker images # REPOSITORY TAG IMAGE ID CREATED SIZE # registry.docker.net/flask 1.0 1bad3fad52ad 24 minutes ago 114MB # alpine latest aded1e1a5b37 3 weeks ago 7.83MB # 启动docker # [root@localhost ~]# docker run -p 5000:5000 --name flask -d registry.docker.net/flask:1.0 # [root@localhost ~]# docker ps -a # CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # 97d8bb75d612 registry.docker.net/flask:1.0 "python ./flask/flas…" 4 seconds ago Up 3 seconds 0.0.0.0:5000->5000/tcp flask # 注意:使用docker save导出的镜像必需用docker load导入,否则导入的镜像将不可用 # 容器健康状态检查 HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ CMD curl -f http://localhost:5000 || exit 1 # 每隔30秒执行一次curl -f http://localhost:5000,容器启动10秒后开始检测,如果失败超过3次且超时在5秒内,该容器被判定为不健康 # CMD curl -f http://localhost:5000:执行的命令,如果命令返回状态码0,表示健康;非0表示不健康 # --interval:两次检测间隔时间,默认30秒 # --timeout:每次检测超时时间,超过认为失败,默认30秒 # --start-period:容器启动后多长时间开始健康检测,默认0 # --retries:失败多少次后标记为不健康,默认3 # 注意:在Dockerfile中只能有一个HEALTHCHECK指令。如果您列出多个,则只有最后一个HEALTHCHECK将生效
13、Dockerfile多阶段构建镜像示例
# 构建阶段命名:AS builder将此阶段命名为builder,后续阶段可以使用FROM ... AS final,并通过COPY --from=builder将构建产物从该阶段拷贝到最终镜像 # Stage: builder FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build # Stage: runtime FROM node:18-alpine WORKDIR /app COPY --from=builder /app/dist ./dist CMD ["node", "dist/index.js"]
14、多架构镜像构建
# 安装buildx mkdir -p /usr/libexec/docker/cli-plugins BUILDX_VERSION=v0.32.1 curl -L "https://github.com/docker/buildx/releases/download/${BUILDX_VERSION}/buildx-${BUILDX_VERSION}.linux-amd64" \ -o /usr/libexec/docker/cli-plugins/docker-buildx chmod +x /usr/libexec/docker/cli-plugins/docker-buildx # 安装QEMU模拟器 docker run --rm --privileged tonistiigi/binfmt --install all # 创建一个支持多平台的builder,--driver docker-container,默认的docker驱动不支持多平台构建,必须切换到docker-container驱动,它会启动一个独立的BuildKit 容器来执行构建任务 docker buildx create --name multiarch --platform linux/amd64,linux/arm64,linux/arm/v7 --driver docker-container --bootstrap --use # 检查支持的平台列表 docker buildx inspect multiarch --bootstrap | grep Platforms: Platforms: linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/loong64, linux/arm/v7, linux/arm/v6 # 查看已创建的builde docker buildx ls # 切换到已存在的builde docker buildx use multiarch # 删除一个builde docker buildx rm multiarch # 构建多架构镜像并把镜像推送到仓库 # --platform,参数指定目标平台,逗号分隔。--push,是必须的。多平台镜像无法直接--load到本地Docker(因为本地只能存一个平台的镜像),所以必须推送到远程仓库 docker buildx build --platform linux/amd64,linux/arm64 -t your-registry/your-app:tag --push . # 本地测试单个平台单独指定,不支持同时指定两个平台:--platform linux/arm64 --load docker buildx build --platform linux/arm64 --pull --no-cache -t myapp:latest --load . # 验证manifest list,你会看到它包含两个平台的 digest,确认构建成功 docker buildx imagetools inspect your-registry/your-app:latest # 安装QEMU用户态模拟器 docker run --rm --privileged multiarch/qemu-user-static --reset -p yes # 使用qemu-user手动模拟 docker run -it --rm --platform linux/arm64 --name myapp myapp:latest /bin/sh # 验证镜像平台 docker image inspect myapp:latest --format '{{.Architecture}}/{{.Os}}'
#!/usr/bin/env bash set -euo pipefail ######################################## # 0) 变量(按需修改) ######################################## REGISTRY="crpi-g05smmlotxjkdb8e.cn-hangzhou.personal.cr.aliyuncs.com" NAMESPACE="xwupiaomiao" BASE_REPO="${REGISTRY}/${NAMESPACE}/alpine" BASE_TAG="3.20-multi" APP_REPO="${REGISTRY}/${NAMESPACE}/myapp" APP_TAG="v1.0.0" # myapp 项目目录(含 Dockerfile) APP_DIR="/root" ######################################## # 1) 登录私有仓库 ######################################## docker login "${REGISTRY}" ######################################## # 2) 安装/注册 binfmt(支持跨架构构建) ######################################## docker run --privileged --rm tonistiigi/binfmt --install all ######################################## # 3) 准备 buildx builder ######################################## docker buildx rm multiarch >/dev/null 2>&1 || true docker buildx create --name multiarch --driver docker-container --use docker buildx inspect --bootstrap ######################################## # 4) 发布多架构 base 到私有仓库 # 用官方 alpine 作为源,推成你私有仓库 tag ######################################## docker buildx build \ --platform linux/amd64,linux/arm64 \ -t "${BASE_REPO}:${BASE_TAG}" \ --pull \ --push \ - <<'EOF' FROM alpine:3.20 EOF ######################################## # 5) 验证 base 是多架构 ######################################## docker buildx imagetools inspect "${BASE_REPO}:${BASE_TAG}" ######################################## # 6) 生成/覆盖 myapp Dockerfile(示例) # 如果你已有 Dockerfile,可只把 FROM 改成私有 multi-arch base ######################################## cat > "${APP_DIR}/Dockerfile" <<EOF FROM ${BASE_REPO}:${BASE_TAG} CMD ["/bin/sh"] EOF ######################################## # 7) 发布 myapp 多架构镜像 ######################################## docker buildx build \ --platform linux/amd64,linux/arm64 \ -t "${APP_REPO}:${APP_TAG}" \ -t "${APP_REPO}:latest" \ --pull \ --push \ "${APP_DIR}" ######################################## # 8) 验证 myapp 是多架构 ######################################## docker buildx imagetools inspect "${APP_REPO}:${APP_TAG}" docker buildx imagetools inspect "${APP_REPO}:latest" ######################################## # 9) 本地拉取并验证 arm64 运行 # docker buildx imagetools inspect <image>:<tag> 里要看到: # linux/amd64 # linux/arm64 # arm64 容器里 readelf -h /bin/sh 要出现 Machine: AArch64 ######################################## docker pull --platform linux/arm64 "${APP_REPO}:${APP_TAG}" docker run --rm --platform linux/arm64 "${APP_REPO}:${APP_TAG}" sh -c "readelf -h /bin/sh | grep Machine || true" docker image inspect "${APP_REPO}:${APP_TAG}" --format '{{.Architecture}}/{{.Os}}'
15、 阿里云docker pull镜像报错
[root@localhost ~]# docker pull crpi-g05smmlotxjkdb8e.cn-hangzhou.personal.cr.aliyuncs.com/xxxxxx/alpine Using default tag: latest Error: remote trust data does not exist for crpi-g05smmlotxjkdb8e.cn-hangzhou.personal.cr.aliyuncs.com/xxxxxx/alpine: crpi-g05smmlotxjkdb8e.cn-hangzhou.personal.cr.aliyuncs.com does not have trust data for crpi-g05smmlotxjkdb8e.cn-hangzhou.personal.cr.aliyuncs.com/xxxxxx/alpine # 解决方法,设置环境变量来禁用内容信任,这样运行的Docker pull命令将不会进行内容信任验证 # 临时允许未签名的镜像 [root@localhost ~]# export DOCKER_CONTENT_TRUST=false # 永久设置 [root@localhost ~]# echo "export DOCKER_CONTENT_TRUST=false" >>.bashrc [root@localhost ~]# source ~/.bashrc # 允许使用未签名的镜像源 [root@localhost ~]# echo '{"insecure-registries": ["your-registry-address:port"]}' >/etc/docker/daemon.json # 启动Docker守护进程时添加--insecure-registry [root@localhost ~]# vim /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd --insecure-registry your-registry-address:port
16、docker-compose常用命令
# ==================== 服务启动与停止(最常用) ==================== docker compose up -d # 后台静默启动所有服务,生产/开发首选 docker compose up # 前台启动,实时打印所有服务日志,适合调试 docker compose down # 停止并删除容器、网络,保留数据卷(安全清理) docker compose down -v # 彻底清理:删除容器+网络+数据卷(数据清空,谨慎使用) # ==================== 状态查看与日志排查 ==================== docker compose ps # 快速查看所有服务运行状态、端口、运行时长 docker compose logs # 查看所有服务全部日志 docker compose logs -f web # 实时跟踪 Web 服务动态日志(高频排查问题) docker compose logs --tail=50 db # 只查看数据库最近50行日志,精准定位报错 # ==================== 单服务精准操作 ==================== docker compose restart web # 单独重启指定服务 docker compose stop web # 停止指定服务,保留容器 docker compose start web # 启动已停止的指定服务 docker compose up -d db # 单独启动/更新指定服务 # ==================== 容器进入与交互式操作 ==================== docker compose exec db bash # 进入数据库容器终端 docker compose exec web sh # 进入 Web 服务容器终端 docker compose exec cache redis-cli # 直接连接 Redis 命令行 # ==================== 配置校验与辅助操作 ==================== docker compose config # 校验 YAML 配置文件语法是否报错 docker compose config --services # 列出当前项目所有已定义服务 docker compose top # 查看各容器内部运行进程 # ==================== 部署与运维操作 ==================== docker compose -f docker-compose.yml up -d # 一键后台启动服务 docker compose -f docker-compose.yml ps # 查看服务运行状态 docker compose -f docker-compose.yml down # 停止服务,保留所有数据(文章、主题、插件不丢失) docker compose -f docker-compose.yml down -v # 彻底清空所有数据,重置环境(谨慎使用)
17、docker-compose.yml配置文件示例
services: my-service: # 镜像配置(二选一:直接拉取/本地构建) image: my-image:v1 # 直接使用远程/本地已有镜像 build: . # 从当前目录 Dockerfile 构建镜像 build: # 精细化构建配置 context: ./backend # 构建上下文目录 dockerfile: Dockerfile.prod # 指定专属构建文件 args: # 构建阶段环境变量 - APP_VERSION=v1.0 # 端口映射配置 ports: - "8080:80" # 主机端口:容器端口 - "127.0.0.1:8080:80" # 仅绑定本地访问,禁止外网访问 # 数据挂载配置(两种核心方式) volumes: - ./data:/app/data # 绑定挂载:本地目录与容器目录同步 - my-named-vol:/app/storage # 命名卷:Compose 托管持久化存储 # 环境变量配置(三种写法) environment: - KEY=value # 列表式配置 environment: KEY: value # 字典式配置(更清晰) env_file: - .env # 加载外部环境变量文件(适合存放敏感信息) # 依赖与重启策略 depends_on: - db # 服务启动依赖 restart: unless-stopped # 重启策略:always/on-failure/no/unless-stopped # 网络与资源限制 networks: - frontend deploy: resources: limits: cpus: '1.0' # 限制CPU核心数 memory: 512M # 限制最大内存占用 # 服务健康检查(保障服务稳定运行) healthcheck: test: ["CMD", "curl", "-f", "http://localhost/health"] interval: 30s # 检查间隔 timeout: 10s # 超时判定时间 retries: 3 # 失败重试次数 start_period: 40s # 启动预热等待时间 # 自定义启动配置 command: ["python", "app.py"] # 覆盖镜像默认启动命令 entrypoint: ["/entrypoint.sh"] # 覆盖容器入口脚本 working_dir: /app # 容器工作目录 user: "1000:1000" # 指定容器运行用户
参考链接:
https://docs.docker.com/reference/
https://www.cnblogs.com/acatsmiling/p/18474276 # 二进制安装Docker以及Docker Compose
https://download.docker.com/linux/static/stable/x86_64/ # docker二进制文件下载
https://www.cnblogs.com/fps2tao/p/10557257.html # 修改运行中的docker容器的端口映射
https://www.cnblogs.com/kingsonfu/p/11578073.html # docker容器添加对外映射端口
https://www.cnblogs.com/maohai-kdg/p/13474024.html # docker安装
https://hub-stage.docker.com/_/centos/tags # CentOS docker镜像
https://www.cnblogs.com/zoujiaojiao/p/17021724.html # nsenter命令进入容器网络命名空间
https://blog.csdn.net/qq_35745940/article/details/119900634 # nsenter命令进入容器网络命名空间
https://www.cnblogs.com/lifuqiang/articles/16815740.html # 安装containerd
https://www.akiraka.net/kubernetes/1139.html#18 # docker、ctr、crictl命令对比
https://www.cnblogs.com/hukey/p/17282408.html # ctr命令使用说明
https://icloudnative.io/posts/getting-started-with-containerd/ # Containerd使用教程
https://github.com/containerd/nerdctl # nerdctl工具下载
https://www.cnblogs.com/kissit/p/18366388 # Containerd高级命令行工具nerdctl安装及使用
https://www.cnblogs.com/chen2ha/p/17086900.html # containerd镜像构建工具nerdctl和buildkit
https://github.com/moby/buildkit # buildctl和builkitd下载
https://www.jianshu.com/p/835179171609 # 使用buildkit构建镜像
https://github.com/tech-shrimp/docker_image_pusher # 从github推送镜像到aliyun个人仓库
https://docker.aityp.com/ # 渡渡鸟镜像同步站
https://www.rclogs.com/2024/06/docker-registry-build # 自建Docker镜像/源加速的方法
https://blog.csdn.net/u010702254/article/details/146243390 # x86与Arm多架构Docker镜像打包
https://github.com/xfan1024/qemu-user-static # 在x86架构上运行其它架构的docker
https://docs.podman.org.cn/en/latest/Commands.html # 使用podman命令管理容器
浙公网安备 33010602011771号