Запуск Docker-контейнера от пользователя Linux
При использовании готовых Docker-образов обычно не приходится задумываться о пользователе внутри контейнера. Но для локальной разработки, например с PHP, часто возникают неудобства с правами доступа к файлам.
Проблема
По умолчанию контейнеры Docker собираются и запускаются от имени root. Это не вызывает сложностей, пока вы работаете только через IDE. Но как только вы генерируете файлы через консоль внутри контейнера (например, с помощью php artisan make:model), а затем пытаетесь отредактировать их в IDE – появляется проблема.
При попытке сохранить файл в PhpStorm или VS Code вы увидите сообщение: Failed to save 'Test.php': Insufficient permissions. Select 'Retry as Sudo' to retry as superuser.
Почему так происходит? Файлы, созданные ранее через IDE, имеют владельца с UID 1000 (ваш пользователь на хосте), а файл Test.php, созданный через консоль внутри контейнера, принадлежит root.
root@7e8b1135c23f:/app# ls -l app/Models/ total 16 -rwxrwxr-x 1 1000 1000 1028 Feb 19 04:46 Post.php -rwxrwxr-x 1 1000 1000 825 Feb 19 04:46 Settings.php -rw-r--r-- 1 root root 107 Mar 15 09:32 Test.php -rwxrwxr-x 1 1000 1000 587 Feb 2 07:55 User.php
Такой подход делает разработку неудобной: приходится либо постоянно менять владельца файлов, либо использовать sudo в IDE. Решение – собирать образ с пользователем, соответствующим пользователю на хосте.
Мои настройки Docker окружения
В своей практике я использую три основных файла для настройки окружения:
Makefile– для удобного управления командами и проброса переменных окруженияDockerfile– для сборки образа с созданием нужного пользователяdocker-compose.yml– для передачи аргументов в Dockerfile и запуска сервисов
1. Makefile
Makefile помогает централизовать команды и автоматически передавать UID текущего пользователя:
.PHONY: build up down start stop
HOST_USER_ID:=$(shell id -u ${USER})
export HOST_USER_ID
build:
docker compose build --no-cache
up:
docker compose up -d
down:
docker compose down --remove-orphans
start:
docker compose start
stop:
docker compose stop
id -u ${USER}возвращает числовой UID пользователя, который затем передается в окружение Docker Compose.
2. Dockerfile
В Dockerfile создается группа и пользователь с тем же UID, что и на хосте. Это гарантирует, что файлы, созданные внутри контейнера, будут принадлежать пользователю хоста.
FROM php:8.0-fpm
EXPOSE 9000
ARG HOST_USER
ARG HOST_USER_ID
WORKDIR /app
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
# ...
# Создаем пользователя и группу без домашнего каталога
&& addgroup --gid ${HOST_USER_ID} ${HOST_USER} \
&& adduser --quiet --disabled-password --gecos "" --no-create-home --ingroup ${HOST_USER} --uid ${HOST_USER_ID} ${HOST_USER}
USER ${HOST_USER}
Важно:
--no-create-home– не создавать домашнюю директорию, если она не нужна- Если приложению требуется запись в определенные директории, убедитесь, что пользователь имеет на них права
3. docker-compose.yml
В Compose-файле передаются аргументы сборки, а также монтируются нужные директории:
services:
php-fpm:
build:
context: ./docker/php
dockerfile: Dockerfile
args:
# подставляются из окружения, переданного через Makefile или командную строку
HOST_USER: ${USER}
HOST_USER_ID: ${HOST_USER_ID}
image: myapp-php-fpm:latest
restart: unless-stopped
working_dir: /app
volumes:
- ./docker/php/10-myapp.ini:/usr/local/etc/php/conf.d/10-myapp.ini:ro
- ./:/app
Результат работы
После сборки и запуска контейнера все файлы, созданные через консоль внутри контейнера, будут принадлежать пользователю хоста:
master@69e33465d1c3:/app$ ls -l app/Models/ total 16 -rwxrwxr-x 1 master master 1028 Feb 19 04:46 Post.php -rwxrwxr-x 1 master master 825 Feb 19 04:46 Settings.php -rw-r--r-- 1 master master 107 Mar 15 10:06 Test.php -rwxrwxr-x 1 master master 587 Feb 2 07:55 User.php
Теперь можно спокойно редактировать файлы в IDE без запросов прав суперпользователя. Консольные команды и IDE работают с одними и теми же правами доступа, что делает разработку более комфортной.