How to extend Dockerimages via docker-compose - docker

i try to extend my Basic Images from Webdevops.
I'll try to add the base-app to my Container that already exists.
Thats my docker-compose:
version: "3"
services:
base-app:
image: "webdevops/base-app"
restart: always
apache:
image: "webdevops/php-apache-dev:7.2"
container_name: apache
restart: always
ports:
- '80:80'
- '443:443'
depends_on:
- mysql
- base-app
volumes:
- "./:/app"
environment:
- XDEBUG_MODE=develop,debug
- XDEBUG_CLIENT_HOST=host.docker.internal
- XDEBUG_CLIENT_PORT=9003 # 9000=xdebug v2, 9003=v3
- XDEBUG_REMOTE_CONNECT_BACK=0
- XDEBUG_REMOTE_AUTOSTART=1
- XDEBUG_IDE_KEY=docker
- XDEBUG_START_WITH_REQUEST=trigger
extra_hosts:
- "host.docker.internal:host-gateway"
mysql:
image: "mysql:latest"
restart: always
container_name: mysql
ports:
- '3306:3306'
volumes:
- './mysql:/var/lib/mysql'
depends_on:
- base-app
environment:
MYSQL_ROOT_PASSWORD: 'xxxxx'
How to extend my Images with base-app?

You can extend any image using a Dockerfile. For example, you might write a Dockerfile
FROM webdevops/php-apache-dev:7.2
COPY . /app
You can do other steps as required, like RUNning an installation command or setting an alternate CMD you need this image to run. You generally should avoid putting host names or credentials of any sort into the Docker image, leave these as environment: settings in the Compose file.
In your docker-compose.yml file, use a build: block to indicate this image should be built. Do not include an image: line; unless you're specifically planning to push this extended image to a registry; and if you do it must have a different name from the base image.
services:
apache:
build: . # _instead of_ image:
restart: always
depends_on: [...]
ports: [...]
environment: [...]
# no volumes: since the code is already in the image
# container_name: is usually unnecessary

Related

docker-compose force services to create seperate containers even when images are the same

I have 2 services which use the same image:, what can i do, to force docker-compose to generate 2 seperate containers?
Thanks!
EDIT:
Full docker-compose:
version: "3.5"
services:
database:
container_name: proj-database
env_file: ../orm/.env.${PROJ_ENV}
image: postgres
restart: always
ports:
- 5432:5432
networks:
- proj
api:
image: golang:1.17
container_name: proj-api
env_file: ../cryptoModuleAPI/.env.${PROJ_ENV}
restart: always
build: ../cryptoModuleAPI/
links:
- database:database
ports:
- 8080:8080
volumes:
- ../cryptoModuleAPI:/proj/api
- ../orm:/proj/orm
networks:
- proj
admin:
image: golang:1.17
container_name: proj-admin
env_file: ../admin/.env.${PROJ_ENV}
restart: always
build: ../admin/
links:
- database:database
ports:
- 8081:8081
volumes:
- ../admin:/proj/admin
- ../orm:/proj/orm
networks:
- proj
networks:
proj:
external:
name: proj
I just run with docker-compose up
You misunderstand how the build and image directives work when used together.
Paraphrasing the docs,
https://docs.docker.com/compose/compose-file/compose-file-v3/#build
If you specify image as well as build, then Compose names the built image with the value of the image directive.
Compose is going to build two images, both named the same thing. Only one will survive. I'm surprised your app spins up at all!
Provide a different name for the image directive of each service, or leave it out entirely.

docker-compose build with new tag

I have a docker-compose which looks like:
version: '3.2'
services:
jobsaf-server:
build:
context: ./application
dockerfile: Dockerfile.production
container_name: jobsaf-server
env_file:
- ./application/.env
tty: true
depends_on:
- "redis"
- "mongo"
links:
- mongo
- redis
volumes:
- ./application/server:/var/www/app/jobsaf-website/server
- ./application/public/assets:/var/www/app/jobsaf-website/public/assets
- ./application/uploads:/var/www/app/jobsaf-website/uploads
- ./application/sitemaps:/var/www/app/jobsaf-website/sitemaps
- ./application/rss:/var/www/app/jobsaf-website/rss
- "/etc/timezone:/etc/timezone:ro"
- "/etc/localtime:/etc/localtime:ro"
nginx:
image: nginx:stable
tty: true
env_file:
- ./.env
environment:
- NGINX_HOST=${APP_HOST}
- NGINX_PORT=${APP_PORT}
- PUID=1001
- PGID=1001
- TZ=Asia/Kabul
links:
- jobsaf-server
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
- ./nginx/ssl/star_jobs_af.pem:/etc/ssl/star_jobs_af.pem
- ./nginx/ssl/jobs.af.key:/etc/ssl/jobs.af.key
- ./nginx/ssl/star_jobs_af.crt:/etc/ssl/star_jobs_af.crt
ports:
- "80:80"
- "443:443"
mongo:
image: mongo:latest
container_name: mongo
tty: true
env_file:
- ./.env
volumes:
- "db-data:/data/db"
environment:
- MONGO_INITDB_ROOT_USERNAME=${DB_USER}
- MONGO_INITDB_ROOT_PASSWORD=${DB_PASS}
- MONGO_INITDB_DATABASE=admin
ports:
- "0.0.0.0:27017:27017"
redis:
image: redis
container_name: redis
tty: true
volumes:
db-data:
# - /data/db
networks:
front-tier:
back-tier:
It build jobsaf-server:latest by default.
what I want is to keep the old tag and build the new one.
let say, while building the images I should pass something similar to this
docker-compose -f docker-compose.production --tag=1.0.1
the above command should build for me and image with tag jobsaf-server:1.0.1
Is it really possible to have such result?
Or is there any alternative solution for it
Thanks in advance.
Note: I want to keep the old image, in case if my new image has issue, then I can use the old image.
version: '3.2'
services:
jobsaf-server:
image: jobsaf-server:${TAG}
build:
context: ./application
dockerfile: Dockerfile.production
...
The best way to supply the tag is with a .env file like this:
TAG=1.0.1
Docker-compose will pick this up automatically.
From #Mihai suggestion following steps worked for me, incase if someone else needed.
version: '3.2'
services:
jobsaf-server:
image: jobsaf-server:${TAG}
build:
context: ./application
dockerfile: Dockerfile.production
To build:
Run TAG=1.0 docker-compose build it will create jobsaf-server:1.0
To Up:
Run TAG=1.0 docker-compose up -d
To down:
Run TAG=1.0 docker-compose down
Note: we can add TAG to .env file also by default.

Dockerfile - possible command line argument?

I have a value in a Dockerfile called ${APP_NAME}. What is it? If this were bash scripting, I would assume it to be some sort of variable but it hasn't been assigned a value anywhere. Is it a command line argument? If so, how would I pass it in when I wanted to call docker-compose with it?
For reference, the Docker file looks like this:
version: '2'
services:
nginx:
container_name: ${APP_NAME}_nginx
hostname: nginx
build:
context: ./containers/nginx
dockerfile: Dockerfile
ports:
- "80:80"
- "443:443"
volumes:
- .:/app
links:
- phpfpm
networks:
- backend
phpfpm:
container_name: ${APP_NAME}_phpfpm
hostname: phpfpm
expose:
- "9000"
build:
context: ./containers/php-fpm
dockerfile: Dockerfile
working_dir: /app
volumes:
- .:/app
links:
- mysql
networks:
- backend
mysql:
container_name: ${APP_NAME}_mysql
hostname: mysql
build:
context: ./containers/mysql
dockerfile: Dockerfile
volumes:
- ./storage/mysql:/var/lib/mysql
- ${MYSQL_ENTRYPOINT_INITDB}:/docker-entrypoint-initdb.d
environment:
- MYSQL_DATABASE=${DB_DATABASE}
- MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
ports:
- "33061:3306"
expose:
- "3306"
networks:
- backend
networks:
backend:
driver: "bridge"
And actually, I'm probably going to have a lot of questions about docker because I've never really used it before so a reference to Dockerfile syntax would be helpful.
This means that there is probably somewhere in your project .env file which contains variables necessary for docker compose. You can find more about it at the official docker compose docs. It says that you can set default values for environment variables using a .env file, which Compose automatically looks for. Values set in the shell environment override those set in the .env file. Try to find more here: https://docs.docker.com/compose/compose-file/#variable-substitution

Docker compose v3 - "Unsupported config option for volumes:"

I have a yml file with a configuration to run two containers. Here's the file:
web:
build: ./web
ports:
- "8000:8000"
restart: always
volumes:
- website:/www/
nginx:
build: ./nginx
ports:
- "80:80"
restart: always
links:
- web
volumes:
- website:/www/
volumes:
website:
When I run this I always get the following error:
The Compose file '.\docker-compose.yml' is invalid because:
Unsupported config option for volumes: 'website'
I have googled this and I think this is good as it is now. What is wrong with it?
i think you should add version and services in docker-compose file.
version: '3'
services:
web:
build: ./web
ports:
- "8000:8000"
restart: always
volumes:
- website:/www/
nginx:
build: ./nginx
ports:
- "80:80"
restart: always
links:
- web
volumes:
- website:/www/
volumes:
website:
reference :
docker compose file
getting start with docker-compose

Build a single image based on docker compose containers

My compose-yaml has 3 services
I am able to run the containers sucessfully when i am using docker-compose up.
Now i want to build these 3 containers into single image. Is it possible?
here is my
compose-yaml
version: '2'
services:
tomcat:
container_name: tomcatcomposejdk
build: .
image: 'apexits/ubuntu-oracle-jdk8-tomcat9'
ports:
- "8787:8080"
- "5003:5003"
networks:
b:
ipv4_address: 10.5.0.6
expose:
- "8787"
- "5003"
mysql:
container_name: mysqlcompose
build: .
image: 'mysql:5.6.36'
ports:
- "3306:3306"
expose:
- "3306"
networks:
b:
ipv4_address: 10.5.0.7
environment:
MYSQL_DATABASE: "bird251"
MYSQL_ROOT_PASSWORD: "root"
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
volumes:
- ./BIRD251.sql:/tmp/BIRD251.sql
- ./import.sh:/tmp/import.sh
elasticsearch:
container_name: escompose
build: .
image: 'elasticsearch:2.3.4'
ports:
- "9200:9200"
- "9300:9300"
expose:
- "9200"
- "9300"
networks:
b:
ipv4_address: 10.5.0.8
networks:
b:
driver: bridge
ipam:
config:
- subnet: 10.5.0.0/16
gateway: 10.5.0.1
This is not recommended at all. You will need to reverse engineer each image and copy the needed binaries/files into the combined image. The approach for that is to use docker multistage build:
FROM apexits/ubuntu-oracle-jdk8-tomcat9 as tomcat
FROM mysql:5.6.36 as mysql
FROM elasticsearch:2.3.4
COPY --from=tomcat /.../tomcat-installtion .../tomcat-installation
COPY --from=mysql /.../mysql-installtion .../mysql-installation
...
This approach is very trick and you need to reverse engineer each image to figure out which files/folder/config need to be copied onto the combined image...
Alternatively, you can start from one of the images and install the other programs using standard installation guidelines for each.
Even if you are successful with that, you will need to start multiple processes in same container which is not recommended and will introduce many complexities.

Resources