Docker - correct approach for cms development - docker

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

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.

How to install new gems in a rails docker image without rebuilding it

I am trying to create my rails application in a docker environment. I have used volumes to mount source directories from the host at a targeted path inside the container. The application is in the development phase and I need to continuously add new gems to it. I install a gem from the bash of my running container, it installs the gem and the required dependencies. But when I removed the running containers(docker-compose down) and then again instantiated them(docker-compose up), my rails web image shows errors of missing gems. I know re-building the image will add the gems but IS THERE ANY WAY TO ADD GEMS WITHOUT REBUILDING THE IMAGE?
I Followed docker-compose docs for setting the rails app
https://docs.docker.com/compose/rails/#define-the-project
DOCKERFILE
FROM ruby:2.7.1-slim-buster
LABEL MAINTAINER "Prayas Arora" "<prayasa#mindfiresolutions.com>"
# Install apt based dependencies required to run Rails as
# well as RubyGems. As the Ruby image itself is based on a
# Debian image, we use apt-get to install those.
RUN apt-get update \
&& apt-get install -qq -y --no-install-recommends \
build-essential \
libpq-dev \
netcat \
postgresql-client \
nodejs \
&& rm -rf /var/lib/apt/lists/*
ENV APP_HOME /var/www/repository/repository_api
# Configure the main working directory. This is the base
# directory used in any further RUN, COPY, and ENTRYPOINT
# commands.
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME
# Copy the Gemfile as well as the Gemfile.lock and install
# the RubyGems. This is a separate step so the dependencies
# will be cached unless changes to one of those two files
# are made.
COPY ./repository_api/Gemfile $APP_HOME/Gemfile
COPY ./repository_api/Gemfile.lock $APP_HOME/Gemfile.lock
RUN bundle install
# Copy the main application.
COPY ./repository_api $APP_HOME
# Add a script to be executed every time the container starts.
COPY ./repository_docker/development/repository_api/entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
# Expose port 3000 to the Docker host, so we can access it
# from the outside.
EXPOSE 3000
# The main command to run when the container starts. Also
# tell the Rails dev server to bind to all interfaces by
# default.
CMD ["rails","server","-b","0.0.0.0"]
docker-compose.yml
container_name: repository_api
build:
context: ../..
dockerfile: repository_docker/development/repository_api/Dockerfile
user: $UID
env_file: .env
stdin_open: true
environment:
DB_NAME: ${POSTGRES_DB}
DB_PASSWORD: ${POSTGRES_PASSWORD}
DB_USER: ${POSTGRES_USER}
DB_HOST: ${POSTGRES_DB}
volumes:
- ../../repository_api:/var/www/repository/repository_api
networks:
- proxy
- internal
depends_on:
- repository_db
A simple solution is to cache the gems in a docker volume. You can create a volume in docker and attach it to the path to bundle gems. This will maintain a shared state and you will not require to install the gems in every container you spun.
container_name: repository_api
build:
context: ../..
dockerfile: repository_docker/development/repository_api/Dockerfile
user: $UID
env_file: .env
stdin_open: true
environment:
DB_NAME: ${POSTGRES_DB}
DB_PASSWORD: ${POSTGRES_PASSWORD}
DB_USER: ${POSTGRES_USER}
DB_HOST: ${POSTGRES_DB}
volumes:
- ../../repository_api:/var/www/repository/repository_api
- bundle_cache:/usr/local/bundle
networks:
- proxy
- internal
.
.
volumes:
bundle_cache:
Also, a/c to bundler.io, the official Docker images for Ruby assume that you will use only one application, with one Gemfile, and no other gems or Ruby applications will be installed or run in your container. So once you have added all the gems required in your application development, you can remove this bundle_cache volume and rebuild your image with your final Gemfile.

How to create docker compose for hybris commerce

I would like to run hybris with the docker.
I am trying to create a docker to run hybris.
Can anyone help me with this?
This is my code:
UPDATE Question:
When I enter the container (ubuntu) and try to build hybris, there is always an error.
I created the docker-compose and the dockerfile. However, when I run ant clean all in the container the build always fails.
[![![enter image description here][1]][1]
version: '3.3'
services:
db:
image: mysql:5.6
volumes:
- //C/dockerVolumes/db_local_hybris:/var/lib/mysql
container_name: mysql_hybris
hostname: mysql_hybris
ports:
- "3307:3306"
environment:
- MYSQL_ROOT_PASSWORD=***
- MYSQL_DATABASE=***
- MYSQL_USER=***
hybris:
image: miltex/jdk:hybrisDevs
build:
context: .
container_name: hybris_dev
hostname: hybris_dev
ports:
- "8009:8009"
- "8010:8010"
- "9001:9001"
- "9002:9002"
- "1099:1099"
tty: true
links:
- db
Dockerfile
FROM miltex/jdk:1.8
#update
RUN apt-get update
## Run Initial Ant ##
RUN mkdir -p /app/hybris_dev
COPY ./hybris/HYBRISCOMM6700P_10-80003492.ZIP /app/hybris_dev/
RUN cd /app/hybris_dev && unzip HYBRISCOMM6700P_10-80003492.ZIP
#COPY ./bin/hybris-wrapper.sh /app/hybris_dev/hybris/bin/platform/
RUN mkdir /app/hybris_dev/hybris/bin/custom
COPY ./src/custom /app/hybris_dev/hybris/bin/custom
RUN cd /app/hybris_dev/installer && rm -R recipes
RUN mkdir /app/hybris_dev/installer/recipes
COPY ./src/custom/recipes /app/hybris_dev/installer/recipes
#CMD /app/hybris_dev/intaller/install.sh -r local setup ; /app/hybris_dev/hybris/bin/custom/platform/setantenv.sh ; ant clean all
## Copy hybris-wrapper to configure template properties at runtime ##
COPY ./bin/hybris-wrapper.sh /hybris-wrapper.sh
## Expose AJP S-AJP HTTP HTTPS RMI ports ##
EXPOSE 8009 8010 9001 9002 1099
RUN chmod -R 777 /app
#RUN chmod +x /hybris-wrapper.sh
# Run Hybris server
#ENTRYPOINT ["/hybris-wrapper.sh"]
[1]: https://i.stack.imgur.com/uoK3E.png
The mistake was the image I was using before. Now this dockerhub miltex:jdk:1.8 image is working perfectly.

Docker volume is not fully sync directory for one container

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....

Docker container communication - "Could not translate host name \"mydbalias\" to address: Temporary failure in name resolution"

I have a PostgreSQL container and a Swift server container. I need to pass the DB IP to the Server to start it. So I created an alias for DB in my custom bridge network. Have a look at my docker-compose.yml
version: '3'
services:
db:
build: database
image: postgres
networks:
mybridgenet:
aliases:
- mydbalias
web:
image: mywebserver:latest
ports:
- "8000:8000"
depends_on:
- db
networks:
- mybridgenet
environment:
WAIT_HOSTS: db:5432
networks:
mybridgenet:
driver: bridge
Dockerfile to build webserver.
FROM swift:4.2.1
RUN apt-get update && apt-get install --no-install-recommends -y libpq-dev uuid-dev && rm -rf /var/lib/apt/lists/*
EXPOSE 8000
WORKDIR /app
COPY client ./client
COPY Package.swift ./
COPY Package.resolved ./
COPY Sources ./Sources
RUN swift build
COPY pkg-swift-deps.sh ./
RUN chmod +x ./pkg-swift-deps.sh
RUN ./pkg-swift-deps.sh ./.build/debug/bridgeOS
FROM busybox:glibc
COPY --from=0 /app/swift_libs.tar.gz /tmp/swift_libs.tar.gz
COPY --from=0 /app/.build/debug/bridgeOS /usr/bin/
RUN tar -xzvf /tmp/swift_libs.tar.gz && \
rm -rf /tmp/*
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.2.1/wait /wait
RUN chmod +x /wait
CMD /wait && mywebserver db "10.0.2.2"
Database Dockerfile
FROM postgres
COPY init.sql /docker-entrypoint-initdb.d/
The server is started using mybinary mydbalias. Like I said earlier, I pass the alias to start the server. While doing this, I get the following error.
message: "could not translate host name \"mydbalias\" to address: Temporary failure in name resolution\n"
What could be the problem?
UPDATE
After 4 days of a grueling raid, I finally found the rat. He is busybox container. I changed it to ubuntu:16.04 and it's a breeze. Feeling so good about this whole conundrum. Thanks, everyone who helped.
Simplify. There is no need in your explicit network declaration (it is done automatically by docker-compose, nor aliases (services get their host names based on service names)
docker-compose.yml
version: '3'
services:
db:
build: database
image: postgres
web:
image: mywebserver:latest
ports:
- "8000:8000"
depends_on:
- db
environment:
WAIT_HOSTS: db:5432
Then just use db as a hostname to connect to database from web

Resources