12

I have a basic docker container which I build using docker-compose (version 3) to bring up a basic LAMP stack.
The issue I am having is that files created inside the docker container are always owned by root, so I am unable to edit them locally.
I have tried setting the container www-data user to have the same uid as my local user, which works, but new files are still created by root.
How do I create file in the container that I can edit locally?

My compose file;

version: "3"

services:
    webserver:
        build: 
            context: ./docker/containers/webserver
        container_name: 'apache7.1-webserver'
        restart: 'always'
        ports:
            - "80:80"
            - "443:443"
        links: 
            - mysql
        volumes: 
            - ${DOCUMENT_ROOT}:/var/www/html
            - ${PHP_INI}:/usr/local/etc/php/php.ini
            - ${VHOSTS_DIR}:/etc/apache2/sites-enabled
            - ${APACHE_LOG_DIR}:/var/log/apache2
    mysql:
        build: ./docker/containers/mysql
        container_name: 'apache7.1-mysql'
        restart: 'always'
        ports:
            - "3306:3306"
        volumes: 
            - ${MYSQL_DATA_DIR}:/var/lib/mysql
            - ${MYSQL_LOG_DIR}:/var/log/mysql
        environment:
            MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
            MYSQL_DATABASE: ${MYSQL_DATABASE}
            MYSQL_USER: ${MYSQL_USER}
            MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    redis:
        container_name: 'apache7.1-redis'
        image: redis:latest
        ports:
            - "6379:6379"

My webserver Dockerfile;

FROM php:7.1-apache

# Get any build argument overrides
ARG APP_UID
ARG APP_GID

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

RUN apt-get clean -y \
    && apt-get update -y \
    && apt-get install -y \
        g++ \
        locales \
        libxml2-dev \
        php-soap \
        zlib1g-dev \
        libicu-dev \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libpng12-dev \
        libmcrypt-dev \
        libpng12-dev \
        libcurl4-openssl-dev \
        libxml2-dev \
        nano \
    && apt-get clean -y

RUN docker-php-ext-install mysqli mbstring zip intl mcrypt curl json
RUN docker-php-ext-install iconv xml xmlrpc 

RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
    && docker-php-ext-install -j$(nproc) gd

# Add any required locales here and restart php-fpm, note that some locales do not include currencies such as EURO, if
# this is the case then they will need to be generated in addition to main locale
RUN sed -i -e 's/# en_GB.UTF-8 UTF-8/en_GB.UTF-8 UTF-8/' /etc/locale.gen \
    && sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \
    && sed -i -e 's/# pt_BR.UTF-8 UTF-8/pt_BR.UTF-8 UTF-8/' /etc/locale.gen \
    && sed -i -e 's/# de_AT.UTF-8 UTF-8/de_AT.UTF-8 UTF-8/' /etc/locale.gen \
    && sed -i -e 's/# de_AT@euro ISO-8859-15/de_AT@euro ISO-8859-15/' /etc/locale.gen \
    && sed -i -e 's/# de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/' /etc/locale.gen \
    && sed -i -e 's/# fr_FR.UTF-8 UTF-8/fr_FR.UTF-8 UTF-8/' /etc/locale.gen \
    && dpkg-reconfigure --frontend=noninteractive locales \
    && kill -USR2 1

RUN pecl install redis-3.1.2 \
    && pecl install xdebug-2.5.0 \
    && docker-php-ext-enable redis xdebug

# Enable apache modules
RUN a2enmod rewrite headers

# Change www-data user to match the host system UID and GID and chown www directory
RUN usermod --non-unique --uid 1000 www-data \
  && groupmod --non-unique --gid 1000 www-data \
  && chown -R www-data:www-data /var/www
Rooneyl
  • 7,802
  • 6
  • 52
  • 81
  • Apache main process running under `root` user, but Apache workers running under `www-data` user. Usually it is impossible to create data with root privileges with Apache (only Apache logs stored with `root` permissions). Looks like files that you need generated somewhere outside Apache or you using something like `shell_exec('sudo cp a b')` inside PHP code to be able run operation as `root`. I don't know what means `APP_UID` and `APP_GID` but if you set it to `1000` (same as `www-data`) it may solve problem (`root` is using if ARGs not set)? In short: looks like the problem inside application. – rzlvmp Apr 01 '22 at 09:06

2 Answers2

5

You can set the user with the USER directive https://docs.docker.com/engine/reference/builder/#user.

So you would need to for example add USER 1000 or USER www-data in the Dockerfile.

Chris Stryczynski
  • 30,145
  • 48
  • 175
  • 286
3

With the combination of USER instruction and chown command inside the Dockerfile, you could change the PHP user and the owner of the root directory to www-data:

FROM php:8.1.1-fpm
.
.
.
RUN chown -R www-data:www-data /var/www
USER www-data

Not that the USER instruction is at the end of the Dockerfile (or before CMD instruction, if it exists), otherwise you might get permission denied error for the next instructions.

Hamid Mohayeji
  • 3,977
  • 3
  • 43
  • 55