rhel9快速上手Docker

一.配置软件仓库并安装docker-ce

#利用阿里云部署软件仓库

复制代码
[root@docker-node1 ~]# cat > /etc/yum.repos.d/docker.repo << EOF
[docker]
name = docker
baseurl = https://mirrors.aliyun.com/docker-ce/linux/rhel/9.6/x86_64/stable/
gpgcheck = 0
EOF

[root@docker-node1 ~]# dnf makecache
正在更新 Subscription Management 软件仓库。
无法读取客户身份

本系统尚未在权利服务器中注册。可使用 "rhc" 或 "subscription-manager" 进行注册。

docker                                                              7.3 kB/s |  46 kB     00:06
AppStream                                                           3.1 MB/s | 3.2 kB     00:00
BaseOS                                                              2.7 MB/s | 2.7 kB     00:00
元数据缓存已建立。


[root@docker-node1 ~]# dnf search  docker
正在更新 Subscription Management 软件仓库。
无法读取客户身份

本系统尚未在权利服务器中注册。可使用 "rhc" 或 "subscription-manager" 进行注册。

上次元数据过期检查:0:00:13 前,执行于 2026年03月14日 星期六 14时55分07秒。
==================================== 名称 和 概况 匹配:docker =====================================
docker-buildx-plugin.x86_64 : Docker Buildx plugin for the Docker CLI
docker-ce-rootless-extras.x86_64 : Rootless support for Docker
docker-compose-plugin.x86_64 : Docker Compose plugin for the Docker CLI
docker-model-plugin.x86_64 : Docker Model Runner plugin for the Docker CLI
pcp-pmda-docker.x86_64 : Performance Co-Pilot (PCP) metrics from the Docker daemon
podman-docker.noarch : Emulate Docker CLI using podman
======================================== 名称 匹配:docker =========================================
docker-ce.x86_64 : The open-source application container engine
docker-ce-cli.x86_64 : The open-source application container engine


[root@docker-node1 ~]# dnf install docker-ce -y

[root@docker-node1 ~]# vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true    #开启iptables功能

[root@docker-node1 ~]# echo br_netfilter > /etc/modules-load.d/docker_mod.conf
[root@docker-node1 ~]# modprobe -a br_netfilter

[root@docker-node1 ~]# cat  > /etc/sysctl.d/docker.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF

[root@docker-node1 ~]# sysctl --system

[root@docker-node1 ~]# systemctl enable --now docker

二.配置docker加速器

复制代码
[root@docker-node1 ~]# cat > /etc/docker/daemon.json <<EOF
{
    "registry-mirrors": ["https://docker.1ms.run"]
}
EOF
[root@docker-node1 ~]# systemctl restart docker

[root@docker-node1 ~]# docker info
 Registry Mirrors:
  https://docker.1ms.run/

三.docker常用命令

1.镜像查看

2.搜索镜像

docker search

3.下载镜像

docker pull

4.查看镜像提交历史

docker history

5.导出镜像

docker save

6.删除镜像

docker rmi

7.导入镜像

docker load

8.运行镜像

docker run

9.查看运行容器

docker ps

10.查看所有容器

docker ps -a

11.交互模式运行容器

交互运行容器默认退出后会停止

12.运行停止的容器

13.退出交互容器不对其停止

复制代码
[root@docker-node1 ~]# docker attach busybox
/ # [ctrl]+[p]+[q]   #按键
[root@docker-node1 ~]# docker ps -a
CONTAINER ID   IMAGE            COMMAND                   CREATED         STATUS              PORTS     NAMES
4523a4dad041   busybox:latest   "sh"                      4 minutes ago   Up About a minute             busybox

14.查看容器信息

docker inspect

15.容器控制

复制代码
[root@Docker-node1 ~]# docker stop busybox			#停止容器
[root@Docker-node1 ~]# docker kill busybox			#杀死容器,可以使用信号
[root@Docker-node1 ~]# docker start busybox			#开启停止的容器


#在已经运行的容器中执行指定命令
[root@docker-node1 ~]# docker exec busybox touch /root/haha		#非交互
[root@docker-node1 ~]# docker exec  busybox  ls /root
file1
file2
haha

[root@docker-node1 ~]# docker exec  -it  web /bin/bash			#交互的
root@f3e369725fab:/#

#容器删除
[root@docker-node1 ~]# docker rm -f busybox
busybox
[root@docker-node1 ~]# docker stop web
web
[root@docker-node1 ~]# docker rm  web
web

#内容提交
[root@docker-node1 ~]# docker run  -it --name test busybox:latest
/ # touch /root/file
/ # ls /root/
file
ctrl+p+q 退出当前环境并继续运行容器

[root@docker-node1 ~]# docker commit -m "add file" test  busybox-file:latest
sha256:31a32089d241d025a5a54f144f15319cc6fb55be1b41d049f8905a472d5a028e
[root@docker-node1 ~]# docker images
                                                                                                i Info →   U  In Use
IMAGE                       ID             DISK USAGE   CONTENT SIZE   EXTRA
busybox-file:latest         31a32089d241       6.71MB         2.21MB

[root@docker-node1 ~]# docker run  -it --name test busybox-file:latest


#文件在镜像中的复制
[root@docker-node1 ~]# docker run  -it --name test busybox-file:latest
root@docker-node1 ~]# docker cp  test:/root/file  /mnt
Successfully copied 1.54kB to /mnt
[root@docker-node1 ~]# ls /mnt/
file  hgfs


[root@docker-node1 ~]# docker cp   /etc/passwd  test:/root/
Successfully copied 3.07kB to test:/root/
[root@docker-node1 ~]# docker exec test  ls /root
file
passwd

四、端口映射

外部浏览器可以访问到

五、镜像构建

#建立构建目录

#编写构建规则文件

#构建

#查看

复制代码
常用选项:

-d:后台运行容器(守护进程模式)。
--name:为容器指定一个名称(方便管理)。
-p <宿主机端口>:<容器端口>:端口映射(将宿主机的端口映射到容器内的端口)。
-v <宿主机目录>:<容器目录>:挂载卷(将宿主机的目录挂载到容器内)。
--rm:容器停止后自动删除(适合测试)。
交互式运行:使用 -it 选项进入容器,查看内部情况

构建命令

add

ENV

复制代码
>>
ENV NAME=timinglee
RUN ["/bin/sh","-c", "touch /root/$NAME" ]

EXPOSE

复制代码
>>
EXPOSE 8080

#VOLUEM

FROM busybox:latest

LABEL Creater=lee

ENV NAME=timinglee

EXPOSE 8080

VOLUME "/mnt"

RUN ["/bin/sh","-c", "touch /root/$NAME" ]

#测试

root@docker-node1 docker\]# docker run -it --name test --rm lee:v6 \[root@docker-node1 \~\]# docker inspect test \| grep -i mounts -A10 "Mounts": \[ { "Type": "volume", "Name": "951e0ad881eda84a037614657b89cae88adac7c600ac03cd9505c067cee04741", "Source": "/var/lib/docker/volumes/951e0ad881eda84a037614657b89cae88adac7c600ac03cd9505c067cee04741/_data", "Destination": "/mnt", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } \[root@docker-node1 \~\]# cd "/var/lib/docker/volumes/951e0ad881eda84a037614657b89cae88adac7c600ac03cd9505c067cee04741/_data" \[root@docker-node1 _data\]# touch lee{1..5} #在容器中 / # ls /mnt/ lee1 lee2 lee3 lee4 lee5 #WORKDIR FROM busybox:latest LABEL Creater=lee ENV NAME=timinglee EXPOSE 8080 VOLUME "/mnt" RUN \["/bin/sh","-c", "touch /root/$NAME"

WORKDIR "/mnt"

root@docker-node1 docker\]# docker run -it --name test --rm lee:v7 /mnt # #CMD #ENV CMD FROM busybox MAINTAINER lee@timinglee.org ENV NAME lee #CMD echo $NAME #CMD \["/bin/echo", "$NAME"

CMD ["/bin/sh", "-c", "/bin/echo $NAME"]

root@Docker-node1 docker\]# docker run -it --rm --name test example:v3 lee \]# docker run -it --name test --rm lee:v8 echo haha haha #ENTRYPOINT FROM busybox MAINTAINER lee@timinglee.org ENV NAME lee ENTRYPOINT echo $NAME \[root@Docker-node1 docker\]# docker run -it --rm --name test example:v3 sh lee \[root@docker-node1 docker\]# docker run -it --name test --rm lee:v8 timinglee \[root@docker-node1 docker\]# docker run -it --name test --rm lee:v8 echo haha timinglee docker images \| awk '/\\\/{system("docker rmi "$1)}' #批量删除构建镜像 docker container prune #删除所有已经停止的容器 ### 镜像优化方案 **镜像优化策略** * 选择最精简的基础镜像 * 减少镜像的层数 * 清理镜像构建的中间产物 **方法1.缩减镜像层** [root@server1 docker]# vim Dockerfile FROM centos:7 AS build ADD nginx-1.23.3.tar.gz /mnt WORKDIR /mnt/nginx-1.23.3 RUN yum install -y gcc make pcre-devel openssl-devel && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module --with-http_stub_status_module && make && make install && cd .. && rm -fr nginx-1.23.3 && yum clean all EXPOSE 80 VOLUME ["/usr/local/nginx/html"] CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"] [root@server1 docker]# docker build -t webserver:v2 . [root@server1 docker]# docker images webserver REPOSITORY TAG IMAGE ID CREATED SIZE webserver v2 caf0f80f2332 4 seconds ago 317MB webserver v1 bfd6774cc216 About an hour ago 494MB **方法2.多阶段构建** [root@server1 docker]# vim Dockerfile FROM centos:7 AS build ADD nginx-1.23.3.tar.gz /mnt WORKDIR /mnt/nginx-1.23.3 RUN yum install -y gcc make pcre-devel openssl-devel && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module --with-http_stub_status_module && make && make install && cd .. && rm -fr nginx-1.23.3 && yum clean all FROM centos:7 COPY --from=build /usr/local/nginx /usr/local/nginx EXPOSE 80 VOLUME ["/usr/local/nginx/html"] CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"] [root@server1 docker]# docker build -t webserver:v3 . [root@server1 docker]# docker images webserver REPOSITORY TAG IMAGE ID CREATED SIZE webserver v3 1ac964f2cefe 29 seconds ago 205MB webserver v2 caf0f80f2332 3 minutes ago 317MB webserver v1 bfd6774cc216 About an hour ago 494MB #直接运行会占用shell,用-d在后台运行 docker run -d --name my-nginx -p 80:80 webserver:v3 **方法3.使用最精简镜像** 使用google提供的最精简镜像 **下载地址:** **[https://github.com/GoogleContainerTools/distroless](https://github.com/GoogleContainerTools/distroless "https://github.com/GoogleContainerTools/distroless")** **下载镜像:** docker pull gcr.io/distroless/base 利用最精简镜像构建 [root@server1 ~]# mkdir new [root@server1 ~]# cd new/ [root@server1 new]# vim Dockerfile FROM nginx:1.23 AS base # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones ARG TIME_ZONE RUN mkdir -p /opt/var/cache/nginx && \ cp -a --parents /usr/lib/nginx /opt && \ cp -a --parents /usr/share/nginx /opt && \ cp -a --parents /var/log/nginx /opt && \ cp -aL --parents /var/run /opt && \ cp -a --parents /etc/nginx /opt && \ cp -a --parents /etc/passwd /opt && \ cp -a --parents /etc/group /opt && \ cp -a --parents /usr/sbin/nginx /opt && \ cp -a --parents /usr/sbin/nginx-debug /opt && \ cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \ cp -a --parents /usr/lib/x86_64-linux-gnu/libpcre* /opt && \ cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \ cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \ cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \ cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \ cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \ cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \ cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \ cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime FROM gcr.io/distroless/base-debian11 COPY --from=base /opt / EXPOSE 80 443 ENTRYPOINT ["nginx", "-g", "daemon off;"] [root@server1 new]# docker build -t webserver:v4 . [root@server1 new]# docker images webserver REPOSITORY TAG IMAGE ID CREATED SIZE webserver v4 c0c4e1d49f3d 4 seconds ago 34MB webserver v3 1ac964f2cefe 12 minutes ago 205MB webserver v2 caf0f80f2332 15 minutes ago 317MB webserver v1 bfd6774cc216 About an hour ago 494MB ## 六、搭建docker的私有仓库 ### 搭建简单的Registry仓库 [root@docker ~]# docker pull registry 或者docker load -i registry.tar 开启Registry [root@docker-node1 docker]# docker run -d -p 5000:5000 --restart=always --name registry registry 5e67b13aa1797d449dc639ded6572dacaa1078917625d51bd9b03227eedb72aa [root@docker-node1 docker]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5e67b13aa179 registry "/entrypoint.sh /etc..." 8 seconds ago Up 7 seconds 0.0.0.0:5000->5000/tcp, [::]:5000->5000/tcp registry 上传镜像到仓库中 #给要上传的经镜像大标签 [root@docker ~]# docker tag busybox:latest 172.25.254.10:5000/busybox:latest #docker在上传的过程中默认使用https,但是我们并没有建立https认证需要的认证文件所以会报错 [root@docker ~]# docker push 172.25.254.10:5000/busybox:latest The push refers to repository [172.25.254.10:5000/busybox] Get "https://172.25.254.10:5000/v2/": dial tcp 172.25.254.10:5000: connect: connection refused #配置非加密端口 [root@docker ~]# vim /root/docker/daemon.json { "insecure-registries" : ["http://172.25.254.10:5000"] } [root@docker ~]# systemctl restart docker #上传镜像 [root@docker ~]# docker push 172.25.254.10:5000/busybox:latest The push refers to repository [172.25.254.10:5000/busybox] d51af96cf93e: Pushed latest: digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b size: 527 #查看镜像上传 [root@docker ~]# curl 172.25.254.10:5000/v2/_catalog {"repositories":["busybox"]} ### 为Registry提加密传输 #生成认证key和证书 mkdir certs [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 #查看证书信息 [root@docker-node1 ~]# openssl x509 -in certs/timinglee.org.crt -noout -text #启动registry仓库 [root@docker ~]# docker run -d -p 443:443 --restart=always --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-node1 docker]# docker push reg.timinglee.org/busybox:latest Error response from daemon: Get "https://reg.timinglee.org/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority #docker客户端没有key和证书所以报错 #为客户端建立证书 mkdir -p /etc/docker/certs.d/reg.timinglee.org cp /root/certs/timinglee.org.crt /etc/docker/certs.d/reg.timinglee.org/ca.crt systemctl restart docker [root@docker-node1 ~]# docker push 172.25.254.10:5000/busybox:latest The push refers to repository [172.25.254.10:5000/busybox] 61dfb50712f5: Layer already exists latest: digest: sha256:70ce0a747f09cd7c09c2d6eaeab69d60adb0398f569296e8c0e844599388ebd6 size: 610 i Info → Not all multiplatform-content is present and only the available single-platform image was pushed sha256:b3255e7dfbcd10cb367af0d409747d511aeb66dfac98cf30e97e87e4207dd76f -> sha256:70ce0a747f09cd7c09c2d6eaeab69d60adb0398f569296e8c0e844599388ebd6 [root@docker-node1 ~]# curl -k https://172.25.254.10:5000/v2/_catalog {"repositories":["busybox"]} ### 为仓库建立登陆认证 #安装建立认证文件的工具包 [root@docker docker]# dnf install httpd-tools -y #建立认证文件 [root@docker ~]# mkdir auth [root@docker ~]# htpasswd -Bc auth/htpasswd timinglee #-B 强制使用最安全加密方式,默认用md5加密 New password: Re-type new password: Adding password for user timinglee #添加认证到registry容器中 [root@docker ~]# docker run -d -p 443:443 --restart=always --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 \ -v /root/auth:/auth \ -e "REGISTRY_AUTH=htpasswd" \ -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \ registry [root@docker-node1 ~]# curl -k https://docker-node1/v2/_catalog -u timinglee:123456 {"repositories":["busybox"]} [root@docker-node1 ~]# echo "172.25.254.10 reg.timinglee.org" >> /etc/hosts [root@docker-node1 ~]# docker login reg.timinglee.org Username: timinglee 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 当仓库开启认证后必须登陆仓库才能进行镜像上传 #未登陆情况下上传镜像 [root@docker ~]# docker push reg.timinglee.org/busybox Using default tag: latest The push refers to repository [reg.timinglee.org/busybox] d51af96cf93e: Preparing no basic auth credentials #未登陆情况下也不能下载 [root@docker-node2 ~]# docker pull reg.timinglee.org/busybox Using default tag: latest Error response from daemon: Head "https://reg.timinglee.org/v2/busybox/manifests/latest": no basic auth credentials ### 建企业级私有仓库harbor 先把运行的容器清理 ![](https://i-blog.csdnimg.cn/direct/1cb1f2338d4e4339b750e6a865ff9bd5.png) 新版本docker不兼容,换老版本 dnf remove docker-ce -y dnf install docker-ce-3:28.5.2-1.el9 -y systemctl enable --now docker #拷贝之前生成的证书 mkdir -p /data cp -rp certs/ /data/ ![](https://i-blog.csdnimg.cn/direct/c9243312067d427ab0270151b9632c80.png) 解压harbor资源包到/opt/目录 ![](https://i-blog.csdnimg.cn/direct/bcf1897dfc4442d4b7f04c88a16b5d52.png) 复制模板并编辑 ![](https://i-blog.csdnimg.cn/direct/28d9f0db47a8449e8d6343247f035cf9.png) ![](https://i-blog.csdnimg.cn/direct/3692b0ca3835465c94eb9aea4d9c5c82.png) ![](https://i-blog.csdnimg.cn/direct/2524d21cf8d24344995a5cf18fbee26a.png) #管理harbor的容器 [root@docker harbor]# docker compose stop [root@docker harbor]# docker compose up -d 1.登陆 ![](https://i-blog.csdnimg.cn/img_convert/c7b88d673162fce96b48a10996323250.png) 2.建立仓库项目 ![](https://i-blog.csdnimg.cn/img_convert/58110e1bf7b6b277da9c8ff00a8ca5eb.png) ![](https://i-blog.csdnimg.cn/img_convert/0fca2b1993e597d5dbb074afe071fac6.png) 上传镜像 ![](https://i-blog.csdnimg.cn/direct/bc365bf37234462389af66cc9cf5f747.png) ![](https://i-blog.csdnimg.cn/direct/79abfe9876794f31a62f00f5803906bb.png) 查看上传的镜像 ![](https://i-blog.csdnimg.cn/direct/6a5c90698a1f4c3eb0176f50472b864f.png) #### 其他主机拉取harbor中的镜像 #配置证书 [root@docker-node2 ~]# mkdir -p /etc/docker/certs.d/reg.timinglee.org [root@docker-node1 ~]# scp /root/certs/timinglee.org.crt 172.25.254.20:/etc/docker/certs.d/reg.timinglee.org/ca.crt #配置加速器到服务机 [root@docker-node2 docker]# cat /etc/docker/daemon.json { "registry-mirrors": ["https://reg.timinglee.org"] } #配置解析 [root@docker-node2 docker]# cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 172.25.254.20 docker-node2 172.25.254.10 reg.timinglee.org [root@docker-node2 docker]# systemctl restart docker ![](https://i-blog.csdnimg.cn/direct/fc8526c7d7154828ba1950b5f89d2860.png) ![](https://i-blog.csdnimg.cn/direct/5b09a5d7bbbd41088c35b5395b21761a.png) ## 七、Docker 网络 ### 自定义桥接网络 docker引擎在分配ip时时根据容器启动顺序分配到,谁先启动谁用,是动态变更的 多容器互访用ip很显然不是很靠谱,那么多容器访问一般使用容器的名字访问更加稳定 docker原生网络是不支持dns解析的,自定义网络中内嵌了dns,所以要自定义桥接 [root@docker-node1 ~]# docker network create my_net1 [root@docker-node1 ~]# docker run -d --network my_net1 --name web nginx:1.23 [root@docker-node1 ~]# docker run -it --network my_net1 --name test busybox / # ping web PING web (172.19.0.2): 56 data bytes 64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.163 ms 64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.228 ms 64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.173 ms ### 让不同的自定义网络互通 [root@docker-node1 ~]# docker network create my_net2 [root@docker-node1 ~]# docker run -d --name web1 --network my_net1 nginx:1.23 1ade478eadfe9a7b39f525e11902ffa6f7493367138512bf744aa4736986f73f [root@docker-node1 ~]# docker run -it --name test --network my_net2 busybox:latest / # ifconfig eth0 Link encap:Ethernet HWaddr 22:52:DD:1B:E0:3A inet addr:172.20.0.2 Bcast:172.20.255.255 Mask:255.255.0.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:11 errors:0 dropped:0 overruns:0 frame:0 TX packets:3 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1042 (1.0 KiB) TX bytes:126 (126.0 B) 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) / # ping 172.19.0.2 PING 172.19.0.2 (172.19.0.2): 56 data bytes ping不通 #将test容器中加入网络eth1 [root@docker-node1 ~]# docker network connect my_net1 test / # ifconfig eth0 Link encap:Ethernet HWaddr 22:52:DD:1B:E0:3A inet addr:172.20.0.2 Bcast:172.20.255.255 Mask:255.255.0.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:19 errors:0 dropped:0 overruns:0 frame:0 TX packets:79 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1546 (1.5 KiB) TX bytes:7462 (7.2 KiB) eth1 Link encap:Ethernet HWaddr EA:52:69:48:43:B7 inet addr:172.19.0.3 Bcast:172.19.255.255 Mask:255.255.0.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:9 errors:0 dropped:0 overruns:0 frame:0 TX packets:3 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:726 (726.0 B) TX bytes:126 (126.0 B) 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) / # ping 172.19.0.2 PING 172.19.0.2 (172.19.0.2): 56 data bytes 64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.259 ms 64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.102 ms ### joined容器网络 Joined容器一种较为特别的网络模式,•在容器创建时使用**--network container:容器名**指定。 处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信。 ![](https://i-blog.csdnimg.cn/direct/7ef599a1724845caa05fc9d78517ec96.png) ### joined网络企业实战 #导入镜像 [root@docker-node1 ~]# docker load -i phpmyadmin-latest.tar.gz [root@docker-node1 ~]# docker load -i mysql-8.0.tar #运行容器 [root@docker-node1 ~]# docker run -d --name phpmyadmin -e PMA_ARBITRARY=1 -p 80:80 phpmyadmin:latest [root@docker-node1 ~]# docker run -d --name mysql -e MYSQL_ROOT_PASSWORD='lee' --network container:phpmyadmin mysql:8.0 ![](https://i-blog.csdnimg.cn/direct/f2bff1283e37478890e969244207167b.png) ![](https://i-blog.csdnimg.cn/direct/fd6b60ba015b49ae87128773696be52e.png) ### 容器内外网的访问 | 特性 | PREROUTING 链 | POSTROUTING 链 | |----------|-------------------------|------------------------| | **处理阶段** | 数据包刚进入系统,**路由决策之前** | 数据包即将离开系统,**路由决策之后** | | **主要用途** | **目的地址转换 (DNAT)** | **源地址转换 (SNAT)** | | **修改对象** | 数据包的**目的IP地址/端口** | 数据包的**源IP地址/端口** | | **影响范围** | 所有进入本机的流量(无论是发往本机还是转发) | 所有离开本机的流量(无论是本机发出还是转发) | | **典型应用** | 端口映射、负载均衡、将公网流量转发至内网服务器 | 内网共享上网、隐藏内网IP地址、源地址伪装 | #### 容器访问外网 * 在rhel7中,docker访问外网是通过iptables添加地址伪装策略来完成容器网文外网 * 在rhel7之后的版本中通过nftables添加地址伪装来访问外网 ![](https://i-blog.csdnimg.cn/direct/cc692dce553e4d2a8dc8d8d94b73753f.png) #### 外网访问docker容器 ①通过docker-proxy(代理)对数据包进行内转 docker run -d --name webserver -p 80:80 nginx:1.23 ![](https://i-blog.csdnimg.cn/direct/2fcacb6f7fd74657b7e9edb1c2022a13.png) ②通过dnat策略来完成浏览内转(目的地地址转换) ![](https://i-blog.csdnimg.cn/direct/f3bc5dd5acb44e5299947cd5f41da698.png) ### docker跨主机通信 **macvlan网络方式实现跨主机通信** **macvlan网络方式** * Linux kernel提供的一种网卡虚拟化技术。 * 无需Linux bridge,直接使用物理接口,性能极好 * 容器的接口直接与主机网卡连接,无需NAT或端口映射。 * macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络 * vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1\~4094 **macvlan网络间的隔离和连通** * macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的 * 可以在三层上通过网关将macvlan网络连通起来 * docker本身不做任何限制,像传统vlan网络那样管理即可 **实现方法如下**: #两台主机添加仅主机网卡,打开网卡混杂模式: [[root@docker-node1~2 ~]# ip link set eth1 promisc on [root@docker-node1~2 ~]# ip link set up eth1 [root@docker-node1~2 ~]# ifconfig eth1 eth1: flags=4419 mtu 1500 ether 00:0c:29:d1:94:e5 txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 #两主机配置docker自建macvlan网络 [root@docker-node1~2 ~]# docker network create \ -d macvlan \ --subnet 1.1.1.0/24 \ --gateway 1.1.1.1 \ -o parent=eth1 lee #测试跨主机docker是否可以通信 [root@docker-node1 ~]# docker run -it --name busybox --rm --network lee --ip 1.1.1.100 --rm busybox / # ip a 1: lo: mtu 65536 qdisc noqueue qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 9: eth0@if3: mtu 1500 qdisc noqueue link/ether 8a:5f:00:39:70:0e brd ff:ff:ff:ff:ff:ff inet 1.1.1.100/24 brd 1.1.1.255 scope global eth0 valid_lft forever preferred_lft forever / # [root@docker-node2 ~]# docker run -it --name busybox --rm --network lee --ip 1.1.1.200 --rm busybox / # ip a 1: lo: mtu 65536 qdisc noqueue qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 5: eth0@if3: mtu 1500 qdisc noqueue link/ether da:94:b4:d9:b6:0f brd ff:ff:ff:ff:ff:ff inet 1.1.1.200/24 brd 1.1.1.255 scope global eth0 valid_lft forever preferred_lft forever / # ping 1.1.1.100 #在node2开启的容器中ping node1主机中开启容器的地址 PING 1.1.1.100 (1.1.1.100): 56 data bytes 64 bytes from 1.1.1.100: seq=0 ttl=64 time=1.304 ms 64 bytes from 1.1.1.100: seq=1 ttl=64 time=1.196 ms 64 bytes from 1.1.1.100: seq=2 ttl=64 time=1.066 ms 64 bytes from 1.1.1.100: seq=3 ttl=64 time=1.423 ms | 网络模式 | 特点 | |-------------|-----------------| | **Bridge** | 默认模式,NAT转换 | | **Host** | 共享宿主机网络 | | **Macvlan** | 独立MAC/IP,直连物理网络 | | **Overlay** | 跨主机通信 | | **None** | 无网络 | ## 八、docker数据卷 ### bind mount 数据卷 * 是将主机上的目录或文件mount到容器里。 * 使用 -v 选项指定路径,格式 \:\ * -v选项指定的路径,如果不存在,挂载时会自动创建 ![](https://i-blog.csdnimg.cn/direct/08f67564bbe446678341f846c4d75edc.png) ### docker manager 卷 * bind mount必须指定host文件系统路径,限制了移植性 * docker managed volume 不需要指定mount源,docker自动为容器创建数据卷目录 * 默认创建的数据卷目录都在 /var/lib/docker/volumes 中 * 如果挂载时指向容器内已有的目录,原有数据会被复制到volume中 ![](https://i-blog.csdnimg.cn/direct/89323691a9ff441b961793e1b86d8e6e.png) 删除 #清理未使用的 Docker 数据卷 [root@docker-node1 volumes]# docker volume prune WARNING! This will remove anonymous local volumes not used by at least one container. Are you sure you want to continue? [y/N] y #手动建立的需要手动删除 [root@docker-node1 volumes]# docker volume rm zk zk ### 数据卷容器 数据卷容器(Data Volume Container)是 Docker 中一种特殊的容器,主要用于方便地在多个容器之间共享数据卷 ![](https://i-blog.csdnimg.cn/direct/4646a1b4a5f54145a4fc9aca34f30dd4.png) ### bind mount 数据卷和docker managed 数据卷的对比 相同点: 两者都是 host 文件系统中的某个路径 ![](https://i-blog.csdnimg.cn/direct/ea98283049314771897aac3200cab013.png) ### 备份与迁移数据卷 **备份数据卷** ![](https://i-blog.csdnimg.cn/direct/069266c9f8ab4d42bb02a64b98caf9b9.png) **数据恢复** ![](https://i-blog.csdnimg.cn/direct/7ef30782c73b4b6f880c7f73979fe98b.png) ## 九、Docker 的安全优化 ### 更改系统cgroup版本(企业中非必须) #在rhel9中默认使用cgroup-v2 但是cgroup-v2中不利于观察docker的资源限制情况,所以推荐使用cgroup-v1 [root@docker-node1 ~]# mount -t cgroup [root@docker-node1 ~]# mount -t cgroup2 cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot) [root@docker-node1 ~]# grubby --update-kernel=/boot/vmlinuz-$(uname -r) \ > --args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller" [root@docker-node1 ~]# reboot [root@docker-node1 ~]# mount -t cgroup #查看是否切换成cgroup cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd) cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event) cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset) cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer) cgroup on /sys/fs/cgroup/misc type cgroup (rw,nosuid,nodev,noexec,relatime,misc) cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids) cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio) cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio) cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb) cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct) cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma) cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices) cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory) ### Docker资源限制 #### 1.cpu的用量 [root@docker-node1 ~]# docker load -i ubuntu-latest.tar.gz [root@docker-node1 ~]# docker run -it --rm ubuntu:latest root@8505c1c08cc5:/# dd if=/dev/zero of=/dev/null & #疯狂写入 [root@docker-node1 ~]# top #CPU几乎完全占用 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3449 root 20 0 2736 1408 1408 R 100.0 0.1 0:20.45 dd #cpu资源限制 [root@docker-node1 ~]# docker run -it --rm --name test --cpu-period 100000 --cpu-quota 20000 ubuntu root@a46d556cf8e2:/# dd if=/dev/zero of=/dev/null & [root@docker-node1 ~]# top #CPU占用只到两成 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3553 root 20 0 2736 1408 1408 R 19.9 0.1 0:07.45 dd #### 2.cpu优先级 #关闭cpu的核心,当cpu都不空闲下才会出现争抢的情况,为了实验效果我们可以关闭一个cpu核心 root@docker ~]# echo 0 > /sys/devices/system/cpu/cpu1/online [root@docker ~]# cat /proc/cpuinfo processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 58 model name : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz stepping : 9 microcode : 0x21 cpu MHz : 3901.000 cache size : 8192 KB physical id : 0 siblings : 1 core id : 0 cpu cores : 1 ##cpu核心数为1 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 cx16 pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust smep arat md_clear flush_l1d arch_capabilities bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit srbds mmio_unknown bogomips : 7802.00 clflush size : 64 cache_alignment : 64 address sizes : 45 bits physical, 48 bits virtual power management: #开启容器时如果指定了cpu使用优先级,那么设定文件为 [root@docker ~]# cat /sys/fs/cgroup/cpu/docker/"docker id(所要查看容器的id)"/cpu.shares #开启容器并限制资源 [root@docker ~]# docker run -it --rm --cpu-shares 100 ubuntu #设定cpu优先级,最大为1024,值越大优先级越高 root@dc066aa1a1f0:/# dd if=/dev/zero of=/dev/null & [1] 8 root@dc066aa1a1f0:/# top top - 12:16:56 up 1 day, 2:22, 0 user, load average: 1.20, 0.37, 0.20 Tasks: 3 total, 2 running, 1 sleeping, 0 stopped, 0 zombie %Cpu(s): 37.3 us, 61.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 1.0 hi, 0.3 si, 0.0 st MiB Mem : 3627.1 total, 502.5 free, 954.5 used, 2471.7 buff/cache MiB Swap: 2063.0 total, 2062.3 free, 0.7 used. 2672.6 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 8 root 20 0 2736 1536 1536 R 3.6 0.0 0:16.74 dd #cpu被限制 1 root 20 0 4588 3968 3456 S 0.0 0.1 0:00.03 bash 9 root 20 0 8856 5248 3200 R 0.0 0.1 0:00.00 top #开启另外一个容器不限制cpu的优先级 root@17f8c9d66fde:/# dd if=/dev/zero of=/dev/null & [1] 8 root@17f8c9d66fde:/# top top - 12:17:55 up 1 day, 2:23, 0 user, load average: 1.84, 0.70, 0.32 Tasks: 3 total, 2 running, 1 sleeping, 0 stopped, 0 zombie %Cpu(s): 36.2 us, 62.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 1.3 hi, 0.3 si, 0.0 st MiB Mem : 3627.1 total, 502.3 free, 954.6 used, 2471.7 buff/cache MiB Swap: 2063.0 total, 2062.3 free, 0.7 used. 2672.5 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 8 root 20 0 2736 1408 1408 R 94.0 0.0 1:09.34 dd #cpu没被限制 1 root 20 0 4588 3968 3456 S 0.0 0.1 0:00.02 bash 9 root 20 0 8848 5248 3200 R 0.0 0.1 0:00.01 top ### 限制内存使用 [root@docker-node1 cpu]# docker run -d --name test --memory 200M --memory-swap 200M nginx:1.23 74989eeb8e1363cc79536736aad29c32310f1e5c4de14496e18a391bdea21599 [root@docker-node1 ~]# rpm -ivh libcgroup-0.41-19.el8.x86_64.rpm [root@docker-node1 ~]# rpm -ivh libcgroup-tools-0.41-19.el8.x86_64.rpm [root@docker-node1 ~]# ll /sys/fs/cgroup/memory/docker/74989eeb8e1363cc79536736aad29c32310f1e5c4de14496e18a391bdea21599/ #查看容器ID [root@docker-node1 ~]# cgexec -g memory:docker/74989eeb8e1363cc79536736aad29c32310f1e5c4de14496e18a391bdea21599 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=120 记录了120+0 的读入 记录了120+0 的写出 125829120字节(126 MB,120 MiB)已复制,0.0389638 s,3.2 GB/s [root@docker-node1 ~]# cgexec -g memory:docker/74989eeb8e1363cc79536736aad29c32310f1e5c4de14496e18a391bdea21599 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=200 已杀死 #被限制 ### 磁盘io限制 [root@docker-node1 ~]# docker run -it --name test --rm ubuntu:latest root@13382a4ecb9b:/# dd if=/dev/zero of=/bigfile bs=1M count=1000 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB, 1000 MiB) copied, 4.74269 s, 221 MB/s #写入速率限制 [root@docker-node1 ~]# docker run -it --name test --device-write-bps /dev/sda:30M --rm ubuntu:latest root@77ca9257045d:/# dd if=/dev/zero of=/bigfile bs=1M count=100 oflag=direct 100+0 records in 100+0 records out 104857600 bytes (105 MB, 100 MiB) copied, 3.34336 s, 31.4 MB/s ### 容器特权 #在容器中默认情况下即使我是容器的超级用户也无法修改某些系统设定,比如网络 [root@docker-node1 ~]# docker run -it --name test --rm busybox:latest / # ip a 1: lo: mtu 65536 qdisc noqueue qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0@if21: mtu 1500 qdisc noqueue link/ether 1a:c0:4d:a4:20:a4 brd ff:ff:ff:ff:ff:ff inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever / # ip a a 1.2.3.4/24 eth0@if41 ip: either "local" is duplicate, or "eth0@if41" is garbage / # fdisk -l / # exit 这是因为容器使用的很多资源都是和系统真实主机公用的,如果允许容器修改这些重要资源,系统的稳定性会变的非常差 但是由于某些需要求,容器需要控制一些默认控制不了的资源,如何解决此问题,这时我们就要设置容器特权 #如果添加了--privileged 参数开启容器,容器获得权限近乎于宿主机的root用户 [root@docker-node1 ~]# docker run -it --rm --privileged busybox:latest / # fdisk -l Disk /dev/sda: 100 GB, 107374182400 bytes, 209715200 sectors 411206 cylinders, 255 heads, 2 sectors/track Units: sectors of 1 * 512 = 512 bytes Device Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type /dev/sda1 * 4,4,1 1023,254,2 2048 2099199 2097152 1024M 83 Linux /dev/sda2 1023,254,2 1023,254,2 2099200 10307583 8208384 4008M 82 Linux swap /dev/sda3 1023,254,2 1023,254,2 10307584 209715199 199407616 95.0G 83 Linux --privileged=true 的权限非常大,接近于宿主机的权限,为了防止用户的滥用,需要增加限制,只提供给容器必须的权限。此时Docker 提供了权限白名单的机制,使用--cap-add添加必要的权限 capabilities手册地址:[http://man7.org/linux/man-pages/man7/capabilities.7.html](http://man7.org/linux/man-pages/man7/capabilities.7.html "http://man7.org/linux/man-pages/man7/capabilities.7.html") #开启指定白名单权限 #只开启网络权限 [root@docker-node1 ~]# docker run -it --rm --cap-add CAP_NET_ADMIN busybox:latest / # fdisk -l / # ifconfig eth0 Link encap:Ethernet HWaddr 12:C5:18:E8:4D:AE inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:9 errors:0 dropped:0 overruns:0 frame:0 TX packets:3 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:806 (806.0 B) TX bytes:126 (126.0 B) 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) / # ip a a 1.2.3.4/24 dev eth0 / # ip a 1: lo: mtu 65536 qdisc noqueue qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0@if25: mtu 1500 qdisc noqueue link/ether 12:c5:18:e8:4d:ae brd ff:ff:ff:ff:ff:ff inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever inet 1.2.3.4/24 scope global eth0 valid_lft forever preferred_lft forever ## 十、容器编排工具Docker Compose 1. `up` - 创建和启动服务 2. `stop` - 停止服务但保留状态 3. `start` - 重新启动已停止的服务 4. `down` - 完全清理项目 5. `restart` - 重启服务 6. `logs` - 查看服务日志 [root@docker-node1 ~]# mkdir /root/timinglee/ [root@docker-node1 ~]# cd /root/timinglee/ [root@docker-node1 timinglee]# cat docker-compose.yml services: web: image: nginx:1.23 ports: - "80:80" volumes: - lee:/data dbserver: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: lee volumes: lee: [root@docker-node1 timinglee]# docker compose up #会占用终端的 [root@docker-node1 timinglee]# docker compose down [root@docker-node1 timinglee]# docker compose ps NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS [root@docker-node1 ~]# docker compose -f /root/timinglee/docker-compose.yml up -d [+] up 3/3 ✔ Network timinglee_default Created 0.0s ✔ Container timinglee-dbserver-1 Started 0.2s ✔ Container timinglee-web-1 Started [root@docker-node1 timinglee]# docker compose stop [root@docker-node1 timinglee]# docker compose start [root@docker-node1 timinglee]# docker compose down [+] down 3/3 ✔ Container timinglee-dbserver-1 Removed 0.7s ✔ Container timinglee-web-1 Removed 0.1s ✔ Network timinglee_default Removed [root@docker-node1 timinglee]# docker compose restart [+] restart 0/1 [root@docker-node1 timinglee]# docker compose logs web

相关推荐
筱顾大牛2 小时前
Docker安装教程(加汉化!超详细!!!)
运维·docker·容器
没头脑的男大2 小时前
关于tailscale和ssh那些事儿
运维·服务器·ssh
竹之却2 小时前
OpenClaw 接入QQ-Bot + 接入Feishu(飞书)
运维·服务器·飞书·openclaw·qq-bot·opencalw接入qq+飞书
九成宫2 小时前
安装和配置Docker教程(装在其他盘)
运维·docker·容器
小璐资源网2 小时前
UPS电源管理:应对突发断电的应急方案
linux·运维·服务器
janthinasnail2 小时前
使用Docker安装nanobot(超轻量个人AI助手)
docker·容器
grrrr_12 小时前
【工具类】虚拟机 + Ubuntu 安全部署 OpenClaw,联动 Ollama 零成本解锁云端大模型
linux·运维·ubuntu·#openclaw·#小龙虾
HealthScience2 小时前
github怎么授权ssh(私人库授权)
运维·ssh·github
HABuo3 小时前
【linux线程(一)】线程概念、线程控制详细剖析
linux·运维·服务器·c语言·c++·ubuntu·centos