Docker volume is not fully sync directory for one container - docker

I've created simple project for Symfony4 based on php7.3+mariadb via docker-compose. I used Docker for Windows 10 (x64)
It works correctly at one machine but at laptop it doesn't sync correctly with container.
In root folder I have standard Symfony structure with docker files like:
- /config
- /public
- /src
....
- /env
- /docker
- .env
- docker-compose.yaml
...
My actions in Git Bash to start app:
docker-compose build
it works correctly, all actions were finished successfully
docker-compose up -d
it works correctly, both containers run successfully
docker-compose exec app bash
works correctly, console starts
ls
result is docker env
it syncs only 2 directories - docker and env
docker dir was synced not in full mode - only subdirectories structure without files
I tried to detect what reason can be for problem with files sync but I haven't enough knowledge and experience with Docker. docker-compose logs have no errors.
Maybe somebody can help how to detect the reason? It starts once time but after reboot problem occurs again...
docker-compose.yaml:
version: '3'
services:
app:
restart: unless-stopped
build:
context: .
dockerfile: docker/webserver-apache/Dockerfile
image: php:7.3.1-apache-stretch
volumes:
- "./docker/webserver-apache/sites-enabled:/etc/apache2/sites-enabled:ro"
- "./:/var/www/html"
ports:
- 8080:80
networks:
- dphptrainnet
mariadb:
restart: unless-stopped
image: mariadb:10.4.1
networks:
- dphptrainnet
volumes:
- ./env/mariadb/data:/var/lib/mysql
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_PASSWORD}
networks:
dphptrainnet:
Dockerfile:
FROM php:7.3.1-apache-stretch
# Setting up constants for an environment
ENV PHP_MEMORY_LIMIT 512M
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \
php composer-setup.php && \
php -r "unlink('composer-setup.php');" && \
mv composer.phar /usr/local/bin/composer
RUN apt-get update && \
apt-get install -y curl vim git zip unzip
# Setting up httpd issues
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
RUN a2enmod rewrite headers && /etc/init.d/apache2 restart
RUN echo "127.0.0.1 dockertrain.local" >> /etc/hosts
WORKDIR "/var/www/html"
RUN a2enmod rewrite

I've found only one working solution - reshare drive for Docker:
1. Disable shared disk, click Apply
2. Enable shared disk, click Apply
3. Restart application - files were synced
But how I should detect there any problems with drive access? No errors, no logs....

Related

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.

Docker container ubuntu 21 root to root (local machine to container) gives permission issues on file saves

I have just started using Docker as it has been recommended to me as something that makes development easy, but so far it has been nothing but pain. I have installed docker engine (v20.10.12) and docker composer (v 2.2.3) as per the documentation given by docker for Ubuntu OS. Both work as intended.
Whenever I new up a new container with docker compose, no matter the source, I have writing privilege issues to files generated by the docker container (for example a laravel application where I have used php artisan to create a controller file). I have so far pinpointed the issue to be as follows:
By default docker runs as root within the container. It "bridges" the root user to the root user on the local machine and uses root:root to create files on the Ubuntu filesystem (my workspace is placed in ~/workspace/laravel). Then when opening the files in an IDE (vscode in this instance) I get the error:
Failed to save to '<file_name>': insufficient permissions. Select 'Retry as Sudo' to retry as superuser
If I try to parse my own local user into the machine and tells it to use that specific userid and groupid it's all good when I'm using the first user created on the machine (1000:1000) since that will match with the containers default user if we look at the bitnami/laravel docker image for example.
All of this can be fixed by running chown -R yadayada . on the workspace directory every time I use php artisan to create a file. But I do not think this is sustainable or smart in any way shape or form.
How can I tell my docker container to, on startup, to check if a user with my UID and GID exists and if not, then make a user with that id and assign it as a system user?
My docker-compose.yml for this example
version: '3.8'
services:
api_php-database:
image: postgres
container_name: api_php-database
restart: unless-stopped
environment:
POSTGRES_PASSWORD: secret
POSTGRES_DB: laravel_docker
volumes:
- ./postgres-data:/var/lib/postgresql/data
ports:
- '5432:5432'
api_php-apache:
container_name: api_php-apache
build:
context: ./php
ports:
- '8080:80'
volumes:
- ./src:/var/www/laravel_docker
- ./apache/default.conf:/etc/apache2/sites-enabled/000-default.conf
depends_on:
- api_php-database
My Dockerfile for this example
FROM php:8.0-apache
RUN apt update && apt install -y g++ libicu-dev libpq-dev libzip-dev zip zlib1g-dev && docker-php-ext-install intl opcache pdo pdo_pgsql pgsql
WORKDIR /var/www/laravel_docker
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
In general, this is not possible, but there are workarounds (I do not recommend them for production).
The superuser UID is always 0, this is written in the kernel code.
It is not possible to automatically change the ownership of non-root files.
In this case, when developing, you can use these methods:
If superuser rights are not required:
You can create users dynamically, then docker-compose.yml:
version: "3.0"
services:
something:
image: example-image
volumes:
- /user/path1:/container/path1
- /user/path2:/container/path2
# The double $ is needed to indicate that the variable is in the container
command: ["bash", "-c", "chown -R $$HOST_UID:$$HOST_GID /container/path1 /container/path2; useradd -g $$HOST_GID -u $$HOST_UID user; su -s /bin/bash user"]
environment:
HOST_GID: 100
HOST_UID: 1000
Otherwise, if you run commands in a container as root in Bash:
Bash will run the script from the PROMPT_COMMAND variable after each command is executed
This can be used in development by changing docker-compose.yaml:
version: "3.0"
services:
something:
image: example-image
volumes:
- /user/path1:/container/path1
- /user/path2:/container/path2
command: ["bash"]
environment:
HOST_UID: 1000
HOST_GID: 100
# The double $ is needed to indicate that the variable is in the container
PROMPT_COMMAND: "chown $$HOST_UID:$$HOST_GID -R /container/path1 /container/path2"

Docker - correct approach for cms development

I am currently setting up docker for development purpose.
The goal would be to easily setup mysql, apache, php, and the cms (Omeka).
I managed to rewrite a dockerfile and dockercompose that automatically setup the cms for a normal user, but i need to be able to access the CMS source code i wget'd during build.
From my understanding, volumes/binds aren't the solution because they only access files added after build (i tried anyway and couldn't access the files).
Should i write a script the run the compose routine, and then download the files and do the things necessary for installing the cms, or is there a more docker approach to this ?
Here is my docker-compose :
version: '3'
services:
db:
image: mysql:latest
environment:
//some vars. irrelevant
phpmyadmin:
image: phpmyadmin/phpmyadmin
depends_on:
- db
ports:
- 8081:80
omeka:
build: .
depends_on:
- db
ports:
- "8080:80"
environment:
//some vars. Irrelevant
volumes:
- type: bind
source: ./www/
target: /var/www/
volumes:
www:
And my Dockerfile :
FROM php:8.0.3-apache
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y --no-install-recommends \
[some packages]
RUN docker-php-ext-install exif mysqli
# Install omeka
WORKDIR /var/www
RUN git clone --recursive https://github.com/omeka/Omeka.git
RUN chown -R root.www-data Omeka && chmod 775 Omeka
WORKDIR /var/www/Omeka
[....]
# Copy some files, run some commands, set some rights
# Configure apache
COPY omeka.conf /etc/apache2/sites-available/omeka.conf
[....]
# Configure php
[...]
# Add init script
COPY run.sh /run.sh
RUN dos2unix "/run.sh"
RUN chmod 755 /*.sh
EXPOSE 443
CMD ["/run.sh"]
Running this (i removed some vars, and of course config files are lacking for clarity purposes) gives me a www folder that stays empty.
I don't quite understand how i could do this, as i don't exactly know how the files are persistent or not when re-running docker-compose p -d
This is my first docker file as well.
Thank you

mysql docker on mac os "crash" on caching_sha2 when laravel connect

I made factory-reset on my Mac Mini, and I wanna install only Docker and some basic tools like git directly on OS X but other for software I wanna use docker - by other soft I mean app like php, phpstorm, nginx, node, mysql, postgres, phpmyadmin, mysql-workbench... in many versions. I wanna install them using docker to easily manage them. For each of this tool I wana to map folder with e.g. code of my projects or db storagem, configuration etc...
During setup mysql 8 I face strange problem - I was able to login as root to db by phpmyadmin and mysql-workbench but my php 7 laravel appliaction "hangs" during connection. Here is mysql dockerfile:
version: '3.1'
services:
db:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: terefere321
MYSQL_ROOT_HOST: "%"
ports:
- 3306:3306
volumes:
- ./db_files:/var/lib/mysql
Here is docker file + script which allow me to run php via cmd on docker:
FROM php:7.2-apache
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
RUN apt-get update &&\
apt-get install -y \
git \
zlib1g-dev \
zip \
unzip \
&&\
docker-php-ext-install pdo pdo_mysql zip &&\
a2enmod rewrite
Bash script to run php-cmd docker container and "login" to it to get command line:
set -e
cd -- "$(dirname "$0")" # go to script dir - (for macos double clik run)
docker build -t php-cmd .
docker rm -f php-cmd
docker run -d --name php-cmd -v /Volumes/work:/var/www/html php-cmd
docker exec -it php-cmd /bin/bash
Here /Volumes/work is directory with code of my project. After "login" i run php artisan migrate and app hangs for 30s and after throw errors:
SQLSTATE[HY000] [2006] MySQL server has gone away PDO::__construct():
Unexpected server respose while doing caching_sha2 auth : 109
Add default-authentication-plugin=mysql_native_password command to mysql8 dockerfile - so you should get:
version: '3.1'
services:
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_ROOT_PASSWORD: terefere321
MYSQL_ROOT_HOST: "%"
ports:
- 3306:3306
volumes:
- ./db_files:/var/lib/mysql

Using docker-compose to set containers timezones

I have a docker-compose file running a few Dockerfiles to create my containers. I don't want to edit my Dockerfiles to set timezones because they could change at any time by members of my team and I have a docker-compose.override.yml file to make local environment changes. However, one of my containers (a Selenium based one) seems to not pull host time zone and that causes problems for me. Based on that I want to enforce timezones on all my containers. In my Dockerfiles right now I do
ENV TZ=America/Denver
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
And everything works fine. How do I replicate the same command in docker-compose syntax?
This is simple solution:
environment:
- TZ=America/Denver
version "2"
services:
serviceA:
...
environment:
TZ: "America/Denver"
command: >
sh -c "ln -snf /usr/share/zoneinfo/$TZ /etc/localtime &&
echo $TZ > /etc/timezone &&
exec my-main-application"
Edit: The question didn't ask for it but I've just added exec my-main-application to show how the main process would be specified. exec is important here to make sure that my-main-application receives Ctrl-C (SIGINT/SIGKILL).
The easiest solution would be share volume in docker-compose.yml like this
ipchanger:
image: codertarasvaskiv/ipchanger:raspberry
volumes:
- "/etc/localtime:/etc/localtime:ro"
ro - means container can only read from /etc/localtime of host-machine.
version: '3.6'
services:
mysql:
image: mysql:5.6
restart: always
container_name: dev-mysql
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
restart: always
environment:
- TZ=Asia/Shanghai
- MYSQL_ROOT_PASSWORD=password # set the root password
ports:
- '3306:3306'
volumes:
- "/etc/localtime:/etc/localtime:ro"
- "/etc/timezone:/etc/timezone:ro"
This my docker-compose.yaml of mysql
Reminder,you need recreate container,other than restart.
if you change the yaml need to recreate
docker-compose -f docker-compose.yaml stop
docker-compose -f docker-compose.yaml rm
docker-compose -f docker-compose.yaml start
version: '2'
services:
ServiceA:
image: image:
- '/etc/localtime:/etc/localtime:ro'
Got the same problem on my Docker engine using Linux containers.
Resolved it by adding a script for installing tzdata package and setting the time zone to final stage of DockerFile for all targeted services using dated processes. The time zone is shared between all images like below:
.env file
COMMON_TIME_ZONE=Europe/Paris
docker-compose.yml
services:
matfront:
build:
context: ./my-app
args:
- TIME_ZONE=$COMMON_TIME_ZONE
Dockerfile
FROM tomcat:9.0
ARG TIME_ZONE
RUN rm -rf /usr/local/tomcat/webapps/*
COPY --from=maven /tmp/ApiDemo/target/ApiDemo.war /usr/local/tomcat/webapps
### Here is the script block that defines the desired timezone ###
# Get the package tzdata that is not installed by default, then set the defined TZ
RUN apt-get install tzdata
RUN ln -snf /usr/share/zoneinfo/${TIME_ZONE} /etc/localtime && echo ${TIME_ZONE} > /etc/timezone
EXPOSE 8080
CMD ["/usr/local/tomcat/bin/catalina.sh", "run"]

Resources