Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cross-OS compatible way to map user in docker

Tags:

docker

chmod

Introduction

I am setting up a project where we try to use docker for everything.

It's php(symfony) + npm project. We have working and battle-tested (we are using this setup for more than a year on several projects) docker-compose.yaml.

But to make it for developers more friendly, I came up with setting up bin-docker folder, that is, using direnv, placed first in the user's PATH

/.envrc:

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

Folder contains files, that are supposed to replace bin files with the in-docker ones

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

E.g.php file contains:

#!/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 "$@"

It works great, you can simply use symfony's bin/console and it will "magically" run in the docker-container.

The problem

The only problem and my question is, how to properly map host user to container's user. Properly for all major OS (macOS, Windows(WSL), Linux) because our developers use all of them. I will talk about the npm, because it uses public image anyone can download.

When I do not map user at all, on Linux the files create in mounted volume are the owned by root, and users have to chmod the files afterwards. Not ideal at all.

When I use -u "$(id -u "$USER"):$(id -g "$USER")" it break's because the in-container user now doesn't have rights to create cache folder in container, also on macOS standard UID is 501, which breaks everything.

What is the proper way to map the user, or is there any other better way to do any part of this setup?

Attachments:

docker-compose.yaml: (It's shortened from sensitive or non-important info)

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: Only to properly pass tty status to 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 "$@"
}
like image 337
michalhosna Avatar asked Oct 24 '25 11:10

michalhosna


1 Answers

This may answer your problem. I came across a tutorial as to how to do setup user namespaces in Ubuntu. Note the use case in the tutorial is for using nvidia-docker and restricting permissions. In particular Dr. Kinghorn states in hist post:

The main idea of a user-namespace is that a processes UID (user ID) and GID (group ID) can be different inside and outside of a containers namespace. The significant consequence of this is that a container can have it's root process mapped to a non-privileged user ID on the host.

Which sounds like what you're looking for. Hope this helps.

like image 145
VanBantam Avatar answered Oct 27 '25 01:10

VanBantam



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!