Docker三剑客
docker-machine
docker-compose
docker-swarm
使用"三剑客"可以帮助解决docker host维护,多容器编排部署,多个docker host集群的各个难题。
Docker machine
docker使用了linux的内核技术(namespace,cgroup等),那么如果想在windows或Mac系统上运行docker怎么办呢?
答案是借助虚拟机来实现,也就是说我在windows或Mac上运行一个linux虚拟机,再在虚拟机里运行docker
docker-machine就是docker公司官方提出的,用于在各种平台上快速创建具有docker服务的虚拟机的技术.
参考: https://docs.docker.com/machine/install-machine/#install-machine-directly
Docker compose
详细介绍也可以参考这篇blog
如果要使用docker运行lnmp架构,那么nginx,mysql,php-fpm三个服务运行在一个容器里,还是运行在多个容器里呢?
答案是都可以。
你可以分别放在三个容器中
也可以全部放在一个容器中
还可以nginx+php-fpm共用一个容器, mysql单独一个容器.
甚至还可以分别做多个容器,实现更复杂的架构
但如果实现一个容器架构(微服务架构),一个个的docker run 启动很麻烦,更麻烦的是容器之间的连接与交互。所以我们需要用于容器编排。
docker-compose就是可以做容器编排的小工具,类似于ansible那样在一个YAML文件中定义多个容器与它们之间的联系, 然后只用一条命令将其自动一键部署。
注意: docker-compose 编排的多个容器都是运行在一个docker host上。如果要运行在多个docker host 上,则需要使用docker swarm 集群或kubernetes 集群。
docker安装与配置
可以用脚本安装
#!/bin/bash yum install -y yum-utils device-mapper-persistent-data lvm2 git yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo yum install -y docker-ce mkdir -p /etc/docker tee /etc/docker/daemon.json <<-'EOF' { "log-driver": "json-file", "log-opts": { "max-size": "20m", "max-file": "3", "labels": "container" }, "registry-mirrors": ["https://pilvpemn.mirror.aliyuncs.com"], "exec-opts": ["native.cgroupdriver=systemd"], "live-restore": true } EOF cat >> /etc/sysctl.conf << EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-arptables = 1 net.ipv4.ip_forward = 1 EOF systemctl daemon-reload systemctl enable --now docker
也可以手动安装
使用华为源安装
yum remove docker docker-common docker-selinux docker-engine yum install -y yum-utils device-mapper-persistent-data lvm2 wget -O /etc/yum.repos.d/docker-ce.repo https://repo.huaweicloud.com/docker-ce/linux/centos/docker-ce.repo sed -i 's+download.docker.com+repo.huaweicloud.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo yum clean all && yum makecache fast
配置加速
cat > /etc/docker/daemon.json <<EOF { "log-driver": "json-file", "log-opts": { "max-size": "20m", "max-file": "3", "labels": "container" }, "registry-mirrors": ["https://pilvpemn.mirror.aliyuncs.com"], "exec-opts": ["native.cgroupdriver=systemd"], "live-restore": true } EOF ## 备注 log-opts 可以用来配置 Docker daemon 的日志输出格式、日志级别、最大文件大小等参数。常用的 log-opts 参数包括: - max-size:设置日志文件的最大大小,超过这个大小后,将会自动进行日志轮换,默认为 10m。 - max-file:设置日志文件的最大轮换次数,默认为 3。 - labels:将 Docker 容器的标签添加到日志中。 live-restore 是 Docker 的一个配置选项,它允许在 Docker 容器宕机或者 Docker 服务重启的时候,保持容器的运行状态。当 Docker 容器宕机或者 Docker 服务重启后,Docker 会自动将容器重新启动,并且恢复容器的运行状态和数据。这个配置选项可以提高 Docker 容器的可靠性和稳定性。
启动并检查docker
[root@typeecho typecho]# systemctl daemon-reload [root@typeecho typecho]# systemctl enable --now docker [root@typeecho typecho]# docker -v Docker version 23.0.5, build bc4487a [root@typeecho typecho]# docker info
docker-compose安装
可以直接上github去下载二进制包,将二进制文件下载下来即可使用,GitHub地址
[root@typeecho typecho]# wget https://github.com/docker/compose/releases/download/v2.11.2/docker-compose-`uname -s`-`uname -m` # 如果上面的办法不好使的话,直接用我的下面方法下载 x86环境的linux包也可 [root@typeecho typecho]# wget https://github.com/docker/compose/releases/download/v2.11.2/docker-compose-linux-x86_64 -O /usr/local/bin/docker-compose [root@typeecho typecho]# chmod +x /usr/local/bin/docker-compose [root@typeecho typecho]# docker-compose -v Docker Compose version v2.11.2
使用docker-compose
Docker Compose将所管理的容器分为三层
工程(project)
服务(service)
容器(contaienr)
Docker Compose运行的目录下的所有文件(docker-compose.yml,extends文件或环境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。
一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像,参数,关系。一个服务当中可包括多个容器实例。
使用Compose基本上分为三步:
Dockerfifile 定义应用的运行环境(镜像)
docker-compose.yml 定义组成应用的各服务
docker-compose up -d构建并启动整个应用
docker compose常见语法
docker compose使用YAML格式文件来编排
参考: Docker Compose overview | Docker Documentation
build
指定镜像构建时的dockerfifile目录,格式一般为绝对路径目录或相对路径目录(dockerfifile需要命名为Dockerfifile)
构建完成之后会自动生成一个新的镜像,下次启动默认从这个新镜像启动,镜像名字为 工程名称+服务名称
build: /path/to/build/dir 或者 build: ./dir
image
指定要启动容器的镜像
如果镜像不存在,compose尝试拉它.
如果指定了构建, 可以使用指定的选项构建它,并使用指定的tag进行标记。
image: redis image: ubuntu:14.04 image: tutum/influxdb image: example-registry.com:4000/postgresql image: a4bc65fd
environment
设置镜像变量,它可以保存变量到镜像里面,也就是说启动的容器也会包含这些变量设置
environment 和 Dockerfifile 中的 ENV 指令一样会把变量一直保存在镜像容器中
environment: RACK_ENV: development SHOW: 'true' 或 environment: - RACK_ENV=development - SHOW=true - TZ=Asia/Shanghai # 指定时区
env_file
和environment 类似,但是env_file是通过文件来记录环境变量,在docker-compose.yml中指定文件路径,通常使用相对路径
env_file: - mysql.env
expose
这个标签与Dockerfifile中的 EXPOSE 指令一样,用于指定暴露的端口,但只将端口暴露给连接的服务,而不暴露给主机,同一个docker-compose.yml中只需要暴露端口就可相互访问
expose: - "3000" - "8000"
ports
映射端口,可以使用 HOST:CONTAINER 的方式指定端口,也可以指定容器端口(选择临时主机端口),宿主机会随机映射端口
ports: - "{主机端口}:{容器端口}" ### ports: - "3000" - "3000-3005" - "8000:8000" - "9090-9091:8080-8081" - "49100:22" - "127.0.0.1:8001:8001" - "127.0.0.1:5000-5010:5000-5010" - "6060:6060/udp" ## 除此之外,和docker类似,它也可以直接使用宿主机网络 services: <service_name>: image: <image_name> network_mode: "host" # 指定网络模式为主机
restart
指定Docker容器的重启策略
默认值为 no ,即在任何情况下都不会重新启动容器;
当值为 always 时,容器退出时总是重新启动,(会随着docker服务启动而启动容器);
当值为 on-failure时,当出现 on-failure 报错(非正常退出,退出状态非0),才会重启容器;
当值为unless-stopped时, 在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器
restart: "no" restart: always restart: on-failure restart: on-failure:3 restart: unless-stopped # 备注 restart: on-failure:3 表示如果这个服务在运行过程中发生了错误,Docker 会尝试重新启动它最多 3 次。如果在 3 次重启之后该服务仍然无法正常运行,则 Docker 不再尝试自动重启该服务。这个选项可以保证出现错误时服务能够自动恢复,并且防止服务在错误状态下无限重启浪费资源。
volume
数据卷挂载,可以直接使用 HOST:CONTAINER 这样的格式,或者使用 HOST:CONTAINER:ro 这样的格式,ro代表数据卷是只读的
volumes: # 只是指定一个路径,Docker 会自动在创建一个数据卷(这个路径是容器 内部的)。 - /var/lib/mysql # 使用绝对路径挂载数据卷 - /opt/data:/var/lib/mysql # 以Compose配置文件为中心的相对路径作为数据卷挂载到容器。 - ./cache:/tmp/cache # 使用用户的相对路径(~/ 表示的目录是 /home/<用户目录>/ 或者 /root/)。 - ~/configs:/etc/configs/:ro # 已经存在的命名的数据卷。 - datavolume:/var/lib/mysql - /etc/localtime:/etc/localtime:ro # 使用这条可以直接让容器与宿主机使用相同时区
depends_on
此标签解决了容器的依赖、启动先后的问题
使用docker-compose up web启动,会先启动redis和db,再启动web
version: '3' services: web: build: . depends_on: - db - redis redis: image: redis db: image: mysql
links
链接到其它服务的中的容器, 与link连接一样效果,会连接到其它服务中的容器
web: links: - db - redis - web:static #这种写法是给前面的服务加上一个别名
除上面这些必须掌握的外还有一些常见的参数
version:指定 Docker Compose 文件的版本号,例如 version: "3.9"。
services:定义各个服务的配置信息,每个服务都包括一个名称和一个配置项列表。
container_name:指定容器的名称。
command:指定容器启动时要执行的命令。
network_mode:指定容器使用的网络模式。
networks ,通过 networks 可以配置多个容器之间的网络连接,以便它们能够相互通信。
在 networks 中,可以定义多个网络来满足不同的需求,每个网络都有一个名称和一个驱动程序。常见的网络驱动程序包括 bridge、host、overlay 等。
例如,以下是一个使用 bridge 网络驱动程序的 docker-compose.yml 文件示例:
version: "3.9" services: app: image: my-app networks: - app-network networks: app-network: driver: bridge
在这个示例中,我们定义了一个名为 app-network 的网络,app 服务会使用这个网络。app-network 使用 bridge 驱动程序,因此 app 容器将会被分配到这个网络上。其他服务如果也需要使用这个网络,只需要在它们的配置信息中加入 networks 配置项,并指定同样的网络名称即可。
需要注意的是,使用不同的网络驱动程序会对容器之间的网络连接产生影响,具体可以参考 Docker 官方文档的相关说明。
通过docker-compose部署一个博客系统
本次部署typecho 最新版本,typecho实际上也是lnmp架构,因此我们只需要启动 nginx + php + mysql 3个容器即可部署完成
# 先创建工程目录 [root@typeecho ~]# mkdir typecho/{mysql,nginx,php,typecho} # 前面三个目录都是用来存放对应容器的一些文件,最后一个目录是存放typecho的代码 [root@typeecho ~]# mkdir typecho/mysql/{data,log} # 后面会挂载到mysql容器 [root@typeecho ~]# mkdir typecho/nginx/{ssl,log} # 准备nginx证书文件目录,如果采用http可以忽略,证书我之前直接制作的私有CA证书,这里就直接拿来用了 # 上官网下载软件包 [root@typeecho ~]# wget https://github.com/typecho/typecho/releases/latest/download/typecho.zip -O typecho/typecho/typecho.zip [root@typeecho typecho]# cd /root/typecho/typecho/ [root@typeecho typecho]# unzip typecho.zip [root@typeecho typecho]# chmod 777 usr/uploads # 这里给设置 777 否则后面可能部署的时候报错提示上传目录权限不足
准备docker-compose.yaml
[root@typeecho ~]# cd typecho/ [root@typeecho typecho]# cat docker-compose.yaml version: "3" services: nginx: image: nginx:1.21 container_name: blog-nginx-typecho restart: on-failure:3 ports: - "80:80" - "443:443" environment: - TZ=Asia/Shanghai volumes: - ./typecho:/typecho - ./nginx/:/etc/nginx/conf.d depends_on: - php networks: - blog php: build: ./php # 这里直接build,后面会贴dockerfile container_name: blog-php-typecho restart: on-failure:3 volumes: - ./typecho:/typecho # 和nginx容器挂载的路径保持一致 #expose: # 默认php容器已经expose 9000了,这里可以不写 #- "9000" depends_on: mysql: condition: service_healthy # 需要mysql健康才运行php networks: - blog mysql: image: mysql:5.7 container_name: blog-mysql-typecho restart: on-failure:3 volumes: - ./mysql/data:/var/lib/mysql - ./mysql/log:/var/log/mysql #ports: # 默认mysql容器已经expose 3306了,这里可以不写 #- "3306:3306" command: - --default-authentication-plugin=mysql_native_password - --character-set-server=utf8mb4 - --collation-server=utf8mb4_general_ci - --explicit_defaults_for_timestamp=true healthcheck: # mysql是最重要的,因此做了一个检测,且如果mysql起不来,其余的容器也不会启动 test: ["CMD", "mysqladmin", "-uroot", "-pHuawei@123", "ping", "-h", "127.0.0.1", "--silent"] # 这里也可以不指定用户密码,一旦指定的话就需要和环境变量中定义的一致 interval: 3s retries: 5 environment: - MYSQL_ROOT_PASSWORD=Huawei@123 # 这里是mysql的root密码 - MYSQL_DATABASE=typecho # 这里是起一个db networks: - blog networks: blog:
准备nginx的配置文件
[root@typeecho typecho]# cat nginx/ssl.conf server{ listen 80; charset utf-8; server_name localhost; # localhost或者 _ 表示可以匹配一切,如果是有域名的话这里填写域名 return 301 https://$host$request_uri; # 强制转https } server{ listen 443 ssl; charset utf-8; server_name localhost; # localhost或者 _ 表示可以匹配一切,如果是有域名的话这里填写域名 ssl_certificate conf.d/ssl/nginx.pem; # https 证书地址,可以采用绝对路径或相对路径 ssl_certificate_key conf.d/ssl/nginx-key.pem; # https 证书私钥,可以采用绝对路径或相对路径 ssl_session_timeout 5m; ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4"; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; access_log conf.d/log/typecho_access.log main; # 给typecho单独定义一个日志,可以采用绝对路径或相对路径 if (!-e $request_filename) { rewrite ^(.*)$ /index.php$1 last; } root /typecho/ ; # 指定nginx的根目录,需要和docker-compose.yml中的挂载路径一致 index index.php; location / { index index.php index.html index.htm; if (!-e $request_filename) { rewrite . /index.php last; #Nginx转发php请求到PHP解释器,并配置rewrite规则以便Typecho开启地址重写 } } location ~ \.php(.*)$ { fastcgi_pass php:9000; # 同一个docker-compose.yml文件中的容器可以直接用其他service 的服务名来访问,因此这里不需要写ip 地址,但是需要和service中的名字对应 fastcgi_index index.php; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; fastcgi_split_path_info ^((?U).+\.php)(/?.+)$; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }
准备php的dockerfile
[root@typeecho typecho]# cat php/Dockerfile FROM php:7.3.29-fpm # php:7.4-fpm、 php:8.0-fpm 等多个镜像也都可以用 RUN docker-php-ext-install pdo_mysql\ # 如果安装wordpress请使用 RUN docker-php-ext-install mysqli 否则会报错 && echo "output_buffering = 4096" > /usr/local/etc/php/conf.d/php.ini # 在官方镜像的基础上,添加了 PDO_MYSQL(如果使用 MySQL 作为 Typecho 的数据库,则需安装此扩展),并设置 buffer 为 4kb,即一个内存页
检查一下文件是否正常
[root@typeecho typecho]# tree -L 2 . ├── docker-compose.yaml ├── mysql │ ├── data │ └── logs ├── nginx │ ├── log │ ├── ssl # 这个文件夹存放了ssl证书 │ ├── ssl.conf │ └── ssl.zip # 这个压缩包是我的ssl证书 ├── php │ └── Dockerfile └── typecho ├── admin ├── config.inc.php ├── index.php ├── install ├── install.php ├── LICENSE.txt ├── usr └── var 12 directories, 8 files [root@typeecho typecho]# pwd /root/typecho
准备启动
# 检查是否有镜像、容器 [root@typeecho typecho]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE [root@typeecho typecho]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # 启动 [root@typeecho typecho]# docker-compose up -d # 这条命令执行之后会 pull 镜像,同时会根据 php:7.3.29-fpm 构建一个新的镜像 [+] Running 19/19 ⠿ nginx Pulled 19.6s ⠿ a2abf6c4d29d Pull complete 2.6s ⠿ a9edb18cadd1 Pull complete 3.5s ⠿ 589b7251471a Pull complete 3.5s ⠿ 186b1aaa4aa6 Pull complete 3.6s ⠿ b4df32aa5a72 Pull complete 3.7s ⠿ a0bcbecc962e Pull complete 3.7s ⠿ mysql Pulled 26.6s ⠿ 72a69066d2fe Pull complete 3.9s ⠿ 93619dbc5b36 Pull complete 4.0s ⠿ 99da31dd6142 Pull complete 4.3s ⠿ 626033c43d70 Pull complete 4.5s ⠿ 37d5d7efb64e Pull complete 4.5s ⠿ ac563158d721 Pull complete 5.2s ⠿ d2ba16033dad Pull complete 5.2s ⠿ 0ceb82207cd7 Pull complete 5.3s ⠿ 37f2405cae96 Pull complete 10.6s ⠿ e2482e017e53 Pull complete 10.6s ⠿ 70deed891d42 Pull complete 10.7s [+] Building 15.4s (6/6) FINISHED => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 344B 0.0s => [internal] load metadata for docker.io/library/php:7.3.29-fpm 15.4s => [1/2] FROM docker.io/library/php:7.3.29-fpm@sha256:32feed343f1eeb09c916b774a044d41e951f6807bcde5cf5ab5747c495568a9f 0.0s => CACHED [2/2] RUN docker-php-ext-install pdo_mysql&& echo "output_buffering = 4096" > /usr/local/etc/php/conf.d/php.ini 0.0s => exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:d9fedaa882607bb3ff4101654f11f1a14726453bb0f8d8d3bdc18bcc32f52568 0.0s => => naming to docker.io/library/typecho-php 0.0s [+] Running 4/4 ⠿ Network typecho_blog Created 0.0s ⠿ Container blog-mysql-typecho Started 0.5s ⠿ Container blog-php-typecho Started 0.6s 复制成功,转载请保留本站链接: www.chenjiao.cloud
检查容器状态
[root@typeecho typecho]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE typecho-php latest d9fedaa88260 6 hours ago 453MB nginx 1.21 605c77e624dd 16 months ago 141MB mysql 5.7 c20987f18b13 16 months ago 448MB [root@typeecho typecho]# docker-compose ps -a NAME COMMAND SERVICE STATUS PORTS blog-mysql-typecho "docker-entrypoint.s…" mysql running (healthy) 3306/tcp, 33060/tcp blog-nginx-typecho "/docker-entrypoint.…" nginx running 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp blog-php-typecho "docker-php-entrypoi…" php running 9000/tcp [root@typeecho typecho]# docker-compose logs # 在当前工程目录下这条命令会打印所有当前工程的日志,也可以在后面接上service名字来查看单独容器的日志 [root@typeecho typecho]# docker-compose logs nginx blog-nginx-typecho | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration blog-nginx-typecho | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ blog-nginx-typecho | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh blog-nginx-typecho | 10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf is not a file or does not exist blog-nginx-typecho | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh blog-nginx-typecho | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh blog-nginx-typecho | /docker-entrypoint.sh: Configuration complete; ready for start up blog-nginx-typecho | 2023/05/05 20:27:09 [notice] 1#1: using the "epoll" event method blog-nginx-typecho | 2023/05/05 20:27:09 [notice] 1#1: nginx/1.21.5 blog-nginx-typecho | 2023/05/05 20:27:09 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6) blog-nginx-typecho | 2023/05/05 20:27:09 [notice] 1#1: OS: Linux 3.10.0-1160.el7.x86_64 blog-nginx-typecho | 2023/05/05 20:27:09 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576 blog-nginx-typecho | 2023/05/05 20:27:09 [notice] 1#1: start worker processes blog-nginx-typecho | 2023/05/05 20:27:09 [notice] 1#1: start worker process 22 blog-nginx-typecho | 2023/05/05 20:27:09 [notice] 1#1: start worker process 23 blog-nginx-typecho | 2023/05/05 20:27:09 [notice] 1#1: start worker process 24 blog-nginx-typecho | 2023/05/05 20:27:09 [notice] 1#1: start worker process 25
开始安装typecho
浏览器访问这台服务器的IP地址,并按提示进行操作,在初始化时候数据库地址和 docker-compose.yml中的service名字保持一致
至此typecho就已经安装完成了
小提示
docker-compose每个project默认都会生成一个新的network,如果宿主机上project多就容易造成出现很多network,容易对管理和运维带来困难
[root@typeecho t1]# docker network ls NETWORK ID NAME DRIVER SCOPE 8b234be18efc bridge bridge local 73daa8dfe3b8 host host local ed352cb4a7ba none null local 54cf3b84c405 typecho_blog bridge local
因此我们可以在新的docker-compose中引用已存在的network
新建一个network
[root@typeecho t1]# docker network create mynet 0bbf379479573c9d4207f94bd020c1c87d9019f8fc05d435b3c94b0992918228 [root@typeecho t1]# docker network ls NETWORK ID NAME DRIVER SCOPE 8b234be18efc bridge bridge local 73daa8dfe3b8 host host local 0bbf37947957 mynet bridge local ed352cb4a7ba none null local 54cf3b84c405 typecho_blog bridge local
在docker-compose.yml中引用
version: "3.8" services: web: image: dockercloud/hello-world container_name: web-helloworld networks: - net1 # 这里还是写下面的network名字 ports: - "8080:80" lb: image: dockercloud/haproxy container_name: lb-helloworld networks: - net1 # 这里还是写下面的network名字 ports: - "8000:80" links: - web:static volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - /etc/localtime:/etc/localtime:ro networks: net1: name: mynet # 这里指定外部的network名字 external: true # 这里表示是使用的外部网络
- 应用docker-compose.yml
[root@typeecho t1]# docker-compose up -d ## 如果容器已经起来了,再次 up -d 没用成功应用修改的 yaml文件可以使用如下命令强制新建容器 [root@typeecho t1]# docker-compose up -d --force-recreate [+] Running 2/2 ⠿ Container web-helloworld Started 10.5s ⠿ Container lb-helloworld Started
这样新的project就使用的已有网络了,也不会新建网络