【问题标题】:Cross-OS compatible way to map user in docker在 docker 中映射用户的跨操作系统兼容方式
【发布时间】:2019-07-20 03:46:51
【问题描述】:

简介

我正在建立一个项目,我们尝试将 docker 用于一切。

这是 php(symfony) + npm 项目。我们已经过工作和实战测试(我们在多个项目中使用此设置超过一年)docker-compose.yaml

但是为了对开发者更友好,我想出了设置bin-docker文件夹,也就是使用direnv,放在用户的PATH首位

/.envrc:

export PATH="$(pwd)/bin-docker:$PATH"

文件夹包含文件,应该将 bin 文件替换为 docker 内的文件

❯ tree bin-docker
bin-docker
├── _tty.sh
├── composer
├── npm
├── php
└── php-xdebug

例如php 文件包含:

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PROJECT_ROOT="$(dirname "$DIR")"

source ${DIR}/_tty.sh

if [ $(docker-compose ps php | grep Up | wc -l) -gt 0 ]; then
    docker_compose_exec \
        --workdir=/src${PWD:${#PROJECT_ROOT}} \
        php php "$@"
else
    docker_compose_run \
        --entrypoint=/usr/local/bin/php \
        --workdir=/src${PWD:${#PROJECT_ROOT}} \
        php "$@"
fi

npm:

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PROJECT_ROOT="$(dirname "$DIR")"

source ${DIR}/_tty.sh

docker_run --init \
    --entrypoint=npm \
    -v "$PROJECT_ROOT":"$PROJECT_ROOT" \
    -w "$(pwd)" \
    -u "$(id -u "$USER"):$(id -g "$USER")" \
    mangoweb/mango-cli:v2.3.2 "$@"

它很好用,你可以简单地使用 symfony 的 bin/console,它会“神奇地”在 docker-container 中运行。

问题

唯一的问题和我的问题是,如何正确地将主机用户映射到容器的用户。适用于所有主要操作系统(macOS、Windows(WSL)、Linux),因为我们的开发人员使用所有这些操作系统。我将讨论 npm,因为它使用任何人都可以下载的公共图像。

当我根本不映射用户时,在 Linux 上,在挂载卷中创建的文件归 root 所有,用户必须在之后对文件进行 chmod。一点都不理想。

当我使用-u "$(id -u "$USER"):$(id -g "$USER")" 时,它会中断,因为容器内用户现在无权在容器中创建缓存文件夹,在 macOS 标准 UID 上也是 501,这会破坏一切。

映射用户的正确方法是什么,或者有没有其他更好的方法来完成此设置的任何部分?

附件:

docker-compose.yaml:(它是敏感或非重要信息的缩写)

version: '2.4'

x-php-service-base: &php-service-base
    restart: on-failure
    depends_on:
        - redis
        - elasticsearch
    working_dir: /src
    volumes:
        - .:/src:cached

    environment:
        APP_ENV: dev
        SESSION_STORE_URI: tcp://redis:6379

services:
    elasticsearch:
        image: docker.elastic.co/elasticsearch/elasticsearch:6.2.3
        environment:
            discovery.type: single-node
            xpack.security.enabled: "false"

    kibana:
        image: docker.elastic.co/kibana/kibana:6.2.3
        environment:
            SERVER_NAME: localhost
            ELASTICSEARCH_URL: http://elasticsearch:9200
        depends_on:
            - elasticsearch

    redis:
        image: redis:4.0.8-alpine

    php:
        <<: *php-service-base
        image: custom-php-image:7.2

    php-xdebug:
        <<: *php-service-base
        image: custom-php-image-with-xdebug:7.2

    nginx:
        image: custom-nginx-image
        restart: on-failure
        depends_on:
            - php
            - php-xdebug

_tty.sh: 仅将 tty 状态正确传递给 docker run

if [ -t 1 ]; then
    DC_INTERACTIVITY=""
else
    DC_INTERACTIVITY="-T"
fi

function docker_run {
    if [ -t 1 ]; then
        docker run --rm --interactive --tty=true "$@"
    else
        docker run --rm --interactive --tty=false "$@"
    fi
}

function docker_compose_run {
    docker-compose run --rm $DC_INTERACTIVITY "$@"
}

function docker_compose_exec {
    docker-compose exec $DC_INTERACTIVITY "$@"
}

【问题讨论】:

    标签: docker chmod


    【解决方案1】:

    这可能会回答您的问题。 I came across a tutorial as to how to do setup user namespaces in Ubuntu. 请注意,本教程中的用例是使用 nvidia-docker 并限制权限。特别是 Kinghorn 博士在他的帖子中指出:

    用户命名空间的主要思想是,进程 UID(用户 ID)和 GID(组 ID)在容器命名空间内部和外部可以不同。这样做的重要后果是容器可以将其根进程映射到主机上的非特权用户 ID。

    这听起来像您正在寻找的东西。希望这会有所帮助。

    【讨论】:

    • 我们将对其进行测试,看起来它可能是解决方案。谢谢。您能否在此处粘贴文章中的一些重要部分?网络上的链接有时会失效。如果重要的部分可以保留在 SO 上,那是最好的。
    猜你喜欢
    • 1970-01-01
    • 2019-09-02
    • 2019-09-27
    • 1970-01-01
    • 2018-10-09
    • 1970-01-01
    • 1970-01-01
    • 2018-05-17
    • 1970-01-01
    相关资源
    最近更新 更多