如何 运行 仅以 root 用户身份执行特定命令,而在 docker-compose 中使用默认用户执行其他命令

How to run only specific command as root and other commands with default user in docker-compose

这是我的 Dockerfile。

FROM python:3.8.12-slim-bullseye as prod-env
RUN apt-get update && apt-get install unzip vim -y
COPY requirements.txt /app
RUN pip install -r requirements.txt
USER nobody:nogroup

这就是docker-compose.yml的样子。

api_server:
    build:
      context: .
      target: prod-env
    image: company/server
    volumes:
      - ./shared/model_server/models:/models
      - ./static/images:/images
    ports:
      - 8200:8200
    command: gunicorn -b 0.0.0.0:8200 --threads "8" --log-level info --reload "server:gunicorn_app(command='start', project='app_server')"

我想添加对共享目录的读取、写入和执行权限。

并且还需要 运行 作为 root 的几个其他命令。

所以我每次构建镜像后都必须用root执行这个命令。

docker exec -it -u root api_server_1 bash -c "python copy_stuffs.py; chmod -R a+rwx models; chmod -R a+rwx /images"

现在,我希望 docker-compose 执行这些行。

但如您所见,docker-compose 中的用户Dockerfile[=40 指定的nobody =].那么如何在 docker-compose 文件中执行 root 命令?

我一直在考虑的选项: 从 Dockerfile 安装 sudo 命令并使用 sudo

有没有更好的方法?

docker-compose.yml 中使用相同的映像和卷创建另一个服务。

使用 user: root:rootcommand: your_command_to_run_as_root 为这个新服务覆盖用户,并在启动常规工作容器之前添加对 运行 这个新服务的依赖。

api_server:
    build:
      context: .
      target: prod-env
    image: company/server
    volumes:
      - ./shared/model_server/models:/models
      - ./static/images:/images
    ports:
      - 8200:8200
    command: gunicorn -b 0.0.0.0:8200 --threads "8" --log-level info --reload "server:gunicorn_app(command='start', project='app_server')"
    # This make sure that startup order is correct and api_server_decorator service is starting first
    depends_on:
      - api_server_decorator
api_server_decorator:
    build:
      context: .
      target: prod-env
    image: company/server
    volumes:
      - ./shared/model_server/models:/models
      - ./static/images:/images
    # No ports needed - it is only decorator
    # Overriding USER with root:root
    user: "root:root"
    # Overriding command
    command: python copy_stuffs.py; chmod -R a+rwx models; chmod -R a+rwx /images

还有其他可能性,例如通过删除用户限制来更改 Dockerfile,然后您可以使用入口点脚本以 root 身份作为特权用户执行您想要的操作,并且 运行ning su - nobody 或更好 exec gosu 以保留 PID=1 和适当的信号处理。

在我看来,赋予容器 root 权限的方法非常危险。 如果你想,例如删除容器写入的文件,您还需要在主机上拥有 root 权限。 如果你想让容器访问主机文件系统上的文件,只需 运行 具有适当用户的容器。

api_server:
   user: my_docker_user:my_docker_group

然后在主机上授予该组的权限

sudo chown -R my_docker_user:my_docker_group models

你应该将你需要的所有内容构建到图像本身中,特别是如果你有这种偶尔需要 运行 更新它的过程的用例(你没有尝试使用隔离工具比如 Docker 来模拟本地开发环境)。在你的Docker文件中,COPY将这些目录放入镜像

COPY shared/model_server/models /models
COPY static/images /images

不要不要使这些目录可写,并且不要使目录中的单个文件可执行。目录通常是模式 0755 和文件模式 0644,由 root 拥有,这很好。

在 Compose 设置中,也不要在这些目录上装载主机内容。你应该只有:

services:
  api_server:
    build: .  # use the same image in all environments
    image: company/server
    ports:
      - 8200:8200
    # no volumes:, do not override the image's command:

现在,当您想要更新文件时,可以重建映像(无需中断 运行ning 应用程序,无需 docker exec,也无需备用用户)

docker-compose build api_server

然后相对快速地重新启动,运行在更新后的映像上创建一个新容器

docker-compose up -d