指尖上的记忆指尖上的记忆
首页
  • 基础
  • Laravel框架
  • Symfony框架
  • 基础
  • Gin框架
  • 基础
  • Spring框架
  • 命令
  • Nginx
  • Ai
  • Deploy
  • Docker
  • K8s
  • Micro
  • RabbitMQ
  • Mysql
  • PostgreSsql
  • Redis
  • MongoDb
  • Html
  • Js
  • 前端
  • 后端
  • Git
  • 知识扫盲
  • Golang
🌟 gitHub
首页
  • 基础
  • Laravel框架
  • Symfony框架
  • 基础
  • Gin框架
  • 基础
  • Spring框架
  • 命令
  • Nginx
  • Ai
  • Deploy
  • Docker
  • K8s
  • Micro
  • RabbitMQ
  • Mysql
  • PostgreSsql
  • Redis
  • MongoDb
  • Html
  • Js
  • 前端
  • 后端
  • Git
  • 知识扫盲
  • Golang
🌟 gitHub

docker -p 参数的使用:

  • 问题: 两个laravel11项目,分别通过docker管理,都有如下配置
docker compose build nginx
docker compose build php
docker compose build solr

但是当一个运行起来之后,就会停止另一个项目的container,并且image也只有一份,我也设置了不同的APP_NAME,按道理说会有两套运行的container以及对应的image才是,但是结果不是这样

  • 如下是和docker-compose.yml同级的start.sh脚本
#!/bin/bash
set -u

cd "$(dirname "$0")"

# the local user's UID & GID are required to build the php Docker container
export USER_ID=$(id -u)
export GROUP_ID=$(id -g)

# Delete all untagged images
if [[ $(docker images -q --filter "dangling=true") ]]; then
    echo "Removing untagged Docker images..."
    docker rmi $(docker images -q --filter "dangling=true")
fi

# create docker networks if not existing yet, 这个地方相当于在docker compose 外部创建了网络,作为全局服务之间的通信
echo "Creating Docker networks..."

# build images (will actually only build if images not yet built or if something changed)
echo "Building Docker images..."
docker compose build nginx
docker compose build php
docker compose build solr

# compose up the stack in detached mode and start to follow the logs output
echo "Starting Docker Compose stack in detached mode..."
#clear
docker compose up -d

/bin/bash ./start-monitor.sh
  • 改进一下:
#!/bin/bash
set -eu

cd "$(dirname "$0")"

# 加载 .env 文件
if [ -f .env ]; then
    export $(grep -v '^#' .env | xargs)
else
    echo ".env file not found"
    exit 1
fi

# 确保 APP_NAME 被设置
if [ -z "${APP_NAME:-}" ]; then
    echo "APP_NAME is not set in .env file"
    exit 1
fi

export USER_ID=$(id -u)
export GROUP_ID=$(id -g)

# 清理属于这个项目的悬空镜像
if [[ $(docker images -q --filter "dangling=true" --filter "label=project=${APP_NAME}") ]]; then
    echo "Removing untagged Docker images for ${APP_NAME}..."
    docker rmi $(docker images -q --filter "dangling=true" --filter "label=project=${APP_NAME}")
fi

# 停止并移除现有容器
docker compose -p ${APP_NAME} down --remove-orphans

# 构建镜像
echo "Building Docker images for ${APP_NAME}..."
docker compose -p ${APP_NAME} build nginx || { echo "Failed to build nginx"; exit 1; }
docker compose -p ${APP_NAME} build php || { echo "Failed to build php"; exit 1; }
docker compose -p ${APP_NAME} build solr || { echo "Failed to build solr"; exit 1; }

# 启动栈
echo "Starting Docker Compose stack for ${APP_NAME} in detached mode..."
docker compose -p ${APP_NAME} up -d

# 启动监控
/bin/bash ./start-monitor.sh ${APP_NAME}

上面主要的改动为 添加了读取 .env环境变量的代码,以及通过 -p 使用这个环境变量。再次运行,这个时候两个项目的image会单独生成,对应的container也互相不影响

  • 还有一个stop.sh脚本
#!/bin/bash
set -u -e

cd "$(dirname "$0")"

export USER_ID=$(id -u)
export GROUP_ID=$(id -g)

docker compose down

也需要添加 环境变量以及 -p 参数:

#!/bin/bash
set -eu

cd "$(dirname "$0")"

# 加载 .env 文件
if [ -f .env ]; then
    export $(grep -v '^#' .env | xargs)
else
    echo ".env file not found"
    exit 1
fi

# 确保 APP_NAME 被设置
if [ -z "${APP_NAME:-}" ]; then
    echo "APP_NAME is not set in .env file"
    exit 1
fi

export USER_ID=$(id -u)
export GROUP_ID=$(id -g)

echo "Stopping Docker Compose stack for ${APP_NAME}..."
docker compose -p ${APP_NAME} down
  
//
这个修改后的 stop.sh 脚本做了以下改进:
  
加载 .env 文件,确保我们有 APP_NAME 和其他必要的环境变量。
检查 APP_NAME 是否被正确设置。
使用 docker compose -p ${APP_NAME} down 命令,这确保我们只停止和删除属于特定项目的容器和网络。
  
使用 -p ${APP_NAME} 参数的好处是:
  
它只会影响属于该特定项目的容器和网络。
如果您在同一台机器上运行多个项目,这可以防止意外停止其他项目的容器。
它与 start.sh 中的 up 命令保持一致,确保您启动和停止的是同一组容器。
  
这个方法更安全,因为它只会影响特定项目的 Docker 资源,而不是停止所有以某个前缀开头的容器
  • 疑问: 为什么我明明在通过APP_NAME对两个项目的container做了区分,为什么还会有问题,加了 -p 参数就没问题了
详细解释一下 `-p` 参数的作用,以及为什么即使 `APP_NAME` 只作为容器名称的前缀也能生效:
  
1. Docker Compose 项目名称:
   `-p` 参数设置 Docker Compose 项目名称。这个名称用于给 Docker Compose 创建的所有资源(容器、网络、卷等)添加一个命名空间。
  
2. 资源前缀:
   当您使用 `-p` 参数时,Docker Compose 会自动将项目名称作为前缀添加到它创建的所有资源名称中,除非您在 docker-compose.yml 文件中明确指定了完整的名称。
  
3. 容器命名:
   - 如果您在 docker-compose.yml 中没有指定 `container_name`,Docker Compose 会使用 "项目名称_服务名称_数字" 的格式来命名容器。
   - 如果您指定了 `container_name`,Docker Compose 会使用您指定的名称,但仍然会将这个容器与项目关联。
  
4. 项目隔离:
   使用 `-p` 参数可以创建逻辑上独立的项目,即使它们使用相同的 docker-compose.yml 文件。
  
5. 为什么它仍然有效:
   即使您的 `APP_NAME` 只是作为容器名称的前缀,`-p` 参数仍然有效,因为:
   - Docker Compose 内部会记录哪些容器属于哪个项目。
   - 当您运行 `docker compose -p ${APP_NAME} down` 时,它会查找所有与该项目名称关联的资源,而不仅仅是依赖容器名称。
  
6. 实际工作原理:
   - Docker Compose 使用标签(labels)来跟踪项目中的资源。
   - 每个由 Docker Compose 创建的资源都会带有 `com.docker.compose.project` 标签,其值为项目名称。
   - 当您使用 `-p` 参数时,Docker Compose 会查找带有对应项目标签的所有资源。
  
7. 额外好处:
   使用 `-p` 参数可以让您在同一台机器上运行多个相同配置的项目实例,而不会发生命名冲突。
  
举例说明:
假设您有两个项目,`APP_NAME` 分别为 "project1" 和 "project2":
  
docker compose -p project1 up -d
docker compose -p project2 up -d
  
即使容器名称可能类似(如 "project1-nginx" 和 "project2-nginx"),Docker Compose 仍然能够正确地管理这两个独立的项目。
  
总结:
虽然 `APP_NAME` 主要用作容器名称的前缀,但使用 `-p ${APP_NAME}` 参数可以确保 Docker Compose 正确地管理和隔离不同项目的资源,即使它们使用相似的配置。这提供了更好的项目隔离和管理能力。
  • 总结:
使用 `-p` 参数确实起到了命名空间的作用:

1. 命名空间的作用:
   - `-p` 参数为 Docker Compose 项目创建了一个逻辑上的命名空间。
   - 这个命名空间确保了不同项目之间的资源隔离,即使它们使用相似或相同的服务名称。

2. 问题的根源:
   - 之前没有使用 `-p` 参数时,多个项目可能在 Docker 的默认命名空间中发生冲突。
   - 这可能导致一个项目的操作意外影响到另一个项目的容器或资源。

3. 解决方案的效果:
   - 使用 `-p ${APP_NAME}` 后,每个项目都在自己的命名空间中运行。
   - 这确保了启动、停止、或其他操作只影响指定项目的容器和资源。

4. 增强的项目管理:
   - 现在可以在同一台机器上并行运行多个项目,而不会相互干扰。
   - 每个项目的资源(容器、网络、卷等)都被清晰地分组和标识。

5. 一致性和可维护性:
   - 结合使用 `container_name: "${APP_NAME}-servicename"` 和 `-p ${APP_NAME}` 提供了双重保障。
   - 容器名称直观可读,而项目级别的隔离则由 Docker Compose 在底层管理。

6. 最佳实践:
   - 始终在 Docker Compose 命令中使用 `-p` 参数(例如:`docker compose -p ${APP_NAME} up -d`)。
   - 在 CI/CD 流程或脚本中也要确保包含这个参数。

7. 额外好处:
   - 更容易进行项目级别的操作,如一次性停止或删除所有相关资源。
   - 简化了多环境部署(如开发、测试、预生产环境)的管理。

这个发现强调了在使用 Docker Compose 管理多项目环境时,正确使用项目名称(通过 `-p` 参数)的重要性。它不仅解决了您之前遇到的问题,还为未来的项目管理和扩展提供了更健壮的基础。