代码之家  ›  专栏  ›  技术社区  ›  michalhosna

Docker中跨OS兼容的用户映射方法

  •  0
  • michalhosna  · 技术社区  · 6 年前

    介绍

    我正在建立一个项目,我们试图使用docker的一切。

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

    但为了让开发人员更友好,我想出了 bin-docker 文件夹,即,使用 direnv ,放在用户路径的第一位

    /.envrc :

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

    文件夹包含文件,这些文件应该用Docker中的文件替换bin文件

    ❯ 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 "$@"
    

    它很好,你可以简单的使用Syffon bin/console 它会“神奇地”在Docker容器中运行。

    问题

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

    当我根本不映射用户时,在Linux上,在装入的卷中创建的文件是根用户所有的,用户必须在之后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 "$@"
    }
    
    0 回复  |  直到 6 年前
        1
  •  2
  •   VanBantam    6 年前

    这也许能回答你的问题。 I came across a tutorial as to how to do setup user namespaces in Ubuntu. 注意本教程中的用例用于使用nvidia docker和限制权限。特别是金霍恩博士在《历史邮报》上说:

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

    听起来像是你要找的。希望这有帮助。