Rooneyl
Rooneyl

Reputation: 7902

Docker - Create new files as www-data and not root

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

Upvotes: 12

Views: 39956

Answers (2)

Hamid Mohayeji
Hamid Mohayeji

Reputation: 4285

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.

Upvotes: 2

Chris Stryczynski
Chris Stryczynski

Reputation: 33971

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.

Upvotes: 5

Related Questions