Resolve error with groupadd in Dockerfile - docker

I'm building a PHP 7.4 container from Dockerfile but i have a little problem with groupadd and rights.
The error message on build with docker-compose build --no-cache :
Step 41/46 : RUN groupadd -g ${SITE_GID} www
---> Running in ee94c83629f7
groupadd: invalid group ID 'www'
ERROR: Service 'php' failed to build: The command '/bin/sh -c groupadd -g ${SITE_GID} www' returned a non-zero code: 3
Here's my docker-compose with PHP container :
services:
# PHP
php:
build:
context: docker/php7-fpm
args:
TIMEZONE: ${TIMEZONE}
SITE_UID: ${SITE_UID}
SITE_GID: ${SITE_GID}
user: ${SITE_UID:-1000}:${SITE_GID:-1000}
restart: unless-stopped
hostname: php
volumes:
- ".:/var/www/symfony:rw"
- "./docker/php7-fpm/pool.d/application.conf:/opt/docker/etc/php/fpm/pool.d/application.conf"
- "./docker/php7-fpm/www.conf:/usr/local/etc/php-fpm.d/www.conf"
- "$SSH_AUTH_SOCK:/ssh-agent:ro"
env_file:
- ".env"
environment:
- SSH_AUTH_SOCK=/ssh-agent
working_dir: /var/www/symfony
networks:
- dso_stack
Variables ${SITE_UID} and ${SITE_GID} are defined in .env file :
SITE_UID=XXXX # from command id -u
SITE_GID=YYYY # from command id -g
And my Dockerfile :
ARG PHP_VERSION=7.4
ARG TIMEZONE
ARG SITE_UID
ARG SITE_GID
FROM php:${PHP_VERSION}-fpm
USER root
# Installation of all dependencies..
# Add user for Symfony application
RUN groupadd -g ${SITE_GID} www
RUN useradd -u ${SITE_UID} -ms /bin/bash -g www www
# Copy existing application directory permissions
COPY --chown=www:www . /var/www/symfony
USER www
EXPOSE 9000
CMD ["php-fpm"]
I'm not a docker jedi ^^ so i'm sure there are many little errors but i don't find exactly where. Thank you for answers :)

Related

docker ns remap and uid/gid: how to prevent bind volume permission error?

I have this docker-compose file :
app:
# cap_drop:
# - ALL
# user: "${UID}:${GID}"
cpus: 0.5
mem_limit: 400m
container_name: app
restart: unless-stopped
build:
context: .
dockerfile: ./app/Dockerfile
restart: always
volumes:
- /logs/app:/app/logs
networks:
- backend
environment:
- UID
- GID
When i try to launch the container, i get the error
app | Error: Error: 'logs/gunicorn_error.log' isn't writable [PermissionError(13, 'Permission denied')]
app |
When i look into the /logs folder where the logs are mounted i get:
drwxr-xr-x. 1 200000 165536 6 2 févr. 18:48 logs
and
drwxr-xr-x. 1 200000 165536 0 2 févr. 18:48 app
So my first question is: is the bind volume being created by docker created by the ns-remap user or by the user inside the container?
i have tried to create a user with the same uid and gid as my docker ns remap user uid and gid (which is 500000). Here is the dockerfile:
FROM python:3.8-slim-buster
RUN apt-get update \
# dependencies for building Python packages
&& apt-get install -y build-essential netcat\
# cleaning up unused files
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
&& rm -rf /var/lib/apt/lists/*
RUN groupadd boc -g 500000
RUN useradd -u 500000 -g boc boc
WORKDIR app
COPY --chown=boc:boc app .
RUN chmod u+w,g+w,o+w /app/logs
RUN pip install -r requirements.txt
ARG USERNAME=boc
ARG UID=500000
ARG GID=500000
# Set the username, UID, and GID for the user in the container
USER $USERNAME:$GID:$UID
ENV PYTHONUNBUFFERED=1
ENTRYPOINT gunicorn
But then i get the error:
"failed to solve: Container ID 500000 cannot be mapped to a host ID"
How can i run an unrooted docker container (ns remap being used) and have write permissions on the bin folder docker mounts?
thanks

When does Dockerfile executes, and why groupadd and usereadd not working

I have two questions:
Dockerfile has two command, add group and user, both named www, but didn't create.
How to stop the container created by docker-compose up -d.
I followed this article:
https://www.digitalocean.com/community/tutorials/how-to-set-up-laravel-nginx-and-mysql-with-docker-compose
git clone https://github.com/laravel/laravel.git mylaravel9
Edit docker-compose.yml and Dockerfile, then
docker-compose up -d
The browser "http://localhost" shows, but with an error, a log file with permission problem. This was solved, but not really solved.
docker-compose.yml
version: '3'
services:
#PHP Service
app:
build:
context: .
dockerfile: Dockerfile
image: php:8.1.4-fpm
container_name: app
restart: unless-stopped
tty: true
environment:
SERVICE_NAME: app
SERVICE_TAGS: dev
working_dir: /var/www
volumes:
- ./:/var/www
- ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
networks:
- app-network
#Nginx Service
webserver:
image: nginx:alpine
container_name: webserver
restart: unless-stopped
tty: true
ports:
- "80:80"
- "443:443"
volumes:
- ./:/var/www
- ./nginx/conf.d/:/etc/nginx/conf.d/
networks:
- app-network
#MySQL Service
db:
image: mysql:5.7.22
container_name: db
restart: unless-stopped
tty: true
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: laravel
MYSQL_ROOT_PASSWORD: 123456
SERVICE_TAGS: dev
SERVICE_NAME: mysql
volumes:
- dbdata:/var/lib/mysql/
- ./mysql/my.cnf:/etc/mysql/my.cnf
networks:
- app-network
#Docker Networks
networks:
app-network:
driver: bridge
#Volumes
volumes:
dbdata:
driver: local
Dockerfile:
FROM php:8.1.4-fpm
# Copy composer.lock and composer.json
COPY composer.lock composer.json /var/www/
# Set working directory
WORKDIR /var/www
# Install dependencies
RUN apt-get update && apt-get install -y \
build-essential \
libpng-dev \
libjpeg62-turbo-dev \
libfreetype6-dev \
locales \
zip \
jpegoptim optipng pngquant gifsicle \
vim \
unzip \
git \
curl
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install extensions
RUN docker-php-ext-install pdo_mysql zip exif pcntl
RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/
RUN docker-php-ext-install gd
# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Add user for laravel application
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www
# Copy existing application directory contents
COPY . /var/www
# Copy existing application directory permissions
COPY --chown=www:www . /var/www
# Change current user to www
USER www
# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]
The first question:
When first time do
docker-compose up -d
It pulls things, and run the commands in Dockerfile. There is a problem, which is also solved
failed to solve: executor failed running [/bin/sh -c docker-php-ext-install pdo_mysql mbstring zip exif pcntl]: exit code: 1
A post says the "mbstring" needs to be taken off. Ok, the Dockerfile really used. But there are two commands not working
# Add user for laravel application
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www
Because
docker exec -it app bash
and in the app container's shell
cd /var/www
ls -l
I saw the group and owner is number 1000, not www. Then
cat /etc/passwd
The user and group of "www" doesn't exist! Why?
I manually add the www group and user, and do chmod, the problem of log file permission is solved. But why www doesnt exist? The add commands are in the Dockerfile.
The second question
Exit the app shell, back to Ubuntu
docker ps
Shows three conatiners: php, nginx, mysql. But in docker interface(Windows 11), there is a container named by the folder mylaravel9.
docker stop mylaravel9
It says:
Error response from daemon: No such container: mylaravel9
So I can only stop the whole thing in the docker UI? If I want to use command, I have to stop the three containers? Is it?
There are two significant problems in the setup you show.
volumes:
- ./:/var/www
In the Dockerfile, you COPY --chown content to a different user, but then this volumes: mount hides everything the image setup does in the /var/www directory and replaces it with content from the host. Inside the container you'll see the host's numeric user ID and the possibly-unrelated code from the host. I'd recommend just deleting this line.
build: .
image: php:8.1.4-fpm
This combination tells Compose to build your application from its Dockerfile, then to label the result as the original php:8.1.4-fpm image. When you re-run docker-compose build it will start from the thing labeled as php:8.1.4-fpm, which means you're repeatedly reinstalling your application on top of itself.
Delete the image: line if you're not planning to push the built image to a registry (and if you are, use the name and tag for the built image, not the base image). docker pull php:8.1.4-fpm manually to make sure you have a "good" copy of this base image.
In the context of a Compose project, you don't usually need to use basic docker commands; there are docker-compose wrappers for most operations. If you want to update your application and restart its container it should be enough to
docker-compose build
docker-compose up -d
will will recreate the changed app container but leave the others alone. If you do need to stop an individual container for some reason ("stopped" is a somewhat unusual state) then docker-compose stop can do it.

Cannot hot reload my ionic app integrated with Docker

I have this Dockerfile
FROM node:15.11.0-alpine
#ENVIRONNEMENT
ENV GLIB_PACKAGE_BASE_URL https://github.com/sgerrand/alpine-pkg-glibc/releases/download
ENV GLIB_VERSION 2.25-r0
ENV JAVA_HOME /usr/lib/jvm/java-1.8-openjdk
ENV GRADLE_HOME /usr/local/gradle
ENV GRADLE_VERSION 4.4
ENV ANDROID_HOME /usr/local/android-sdk-linux
ENV ANDRDOID_TOOLS_VERSION r25.2.5
ENV ANDROID_API_LEVELS android-26
ENV ANDROID_BUILD_TOOLS_VERSION 26.0.2
ENV IONIC_VERSION 5
ENV PATH ${GRADLE_HOME}/bin:${JAVA_HOME}/bin:${ANDROID_HOME}/tools:$ANDROID_HOME/platform-tools:$PATH
# INSTALL JAVA
RUN apk update ...
# INSTALL IONIC AND CORDOVA
RUN npm install -g cordova ionic#${IONIC_VERSION}
#INSTALL Graddle
RUN mkdir -p ${GRADLE_HOME} ...
# INSTALL ANDROID
RUN mkdir -p ${ANDROID_HOME} ...
# INSTALL GLIBC
RUN curl -L ...
# CONFIGURATION
RUN echo y | android update sdk --no-ui -a --filter platform-tools,${ANDROID_API_LEVELS},build-tools-${ANDROID_BUILD_TOOLS_VERSION}
# Make license agreement
RUN mkdir $ANDROID_HOME/licenses ...
#FILES DELETION
RUN rm -rf /tmp/* /var/cache/apk/*
WORKDIR /usr/app
RUN npm install
COPY ./ /usr/app
I am building it with CMD:
docker build -t <image-name> .
I have this docker-compose.yml file:
version: '3.6'
services:
app:
container_name: karma5_ionic
build:
context: .
dockerfile: Dockerfile
ports:
- '8100:8100'
- '35729:35729'
command: ionic serve --external
I run the following command:
sudo docker-compose up -d
The application is displaying fine in the browser in localhost:8100
Problem:
When I make changes, there is no hot reload.
localhost:35729 might be temporarily down or it may have moved permanently to a new web address.
Or localhost:35729 the connections was reset
The only way that i can see changes is if I
run docker-compose build
docker-compose up -d again
To whom it may concern:
I just needed to add
volumes:
- "./:/usr/app"
Whole docker-compose.yml file:
version: '3.6'
services:
app:
container_name: karma5_ionic
build:
context: .
dockerfile: Dockerfile
volumes:
- "./:/usr/app"
ports:
- '8100:8100'
- '35729:35729'
command: ionic serve --external

why docker-compose fails when vanila docker succeeds (permission)

I'm trying to run uwsgi, and it works fine if I run with docker run -d foo but fails if I do docker-compose up with error
bind(): Permission denied [core/socket.c line 230]
docker-compose.yml
services:
web:
restart: always
build:
context: .
dockerfile: ./compose/production/web/Dockerfile
image: foo
volumes:
- /app
- /var/log
Dockerfile
....
CMD uwsgi --uid www-data --gid www-data --emperor /app/momsite/momsite/conf/docker/etc/uwsgi/vassals

Docker Image Contains files that Docker Container doesn't

I have a Dockerfile that contains steps that create a directory and runs an angular build script outputing to that directory. This all seems to run correctly. However when the container runs, the built files and directory are not there.
If I run a shell in the image:
docker run -it pnb_web sh
# cd /code/static
# ls
assets favicon.ico index.html main.js main.js.map polyfills.js polyfills.js.map runtime.js runtime.js.map styles.js styles.js.map vendor.js vendor.js.map
If I exec a shell in the container:
docker exec -it ea23c7d30333 sh
# cd /code/static
sh: 1: cd: can't cd to /code/static
# cd /code
# ls
Dockerfile api docker-compose.yml frontend manage.py mysite.log pnb profiles requirements.txt settings.ini web_variables.env
david#lightning:~/Projects/pnb$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ea23c7d30333 pnb_web "python3 manage.py r…" 13 seconds ago Up 13 seconds 0.0.0.0:8000->8000/tcp pnb_web_1_267d3a69ec52
This is my dockerfile:
FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
RUN apt install nodejs
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/
RUN mkdir /code/static
WORKDIR /code/frontend
RUN npm install -g #angular/cli
RUN npm install
RUN ng build --outputPath=/code/static
and associated docker-compose:
version: '3'
services:
db:
image: postgres
web:
build:
context: .
dockerfile: Dockerfile
working_dir: /code
env_file:
- web_variables.env
command: python3 manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
In the second example, the static directory has never been created or built into. I thought that a container is an instance of an image. How can the container be missing files from the image?
You're confusing build-time and run-time, along playing with Volumes.
Remember that host mount has priority over FS provided by the running container, so even your built image has assets, they are going to be overwritten by .services.web.volumes because you're mounting the host filesystem that overwrites the build result.
If you try to avoid volumes mounting you'll notice that everything is working as expected.

Resources