Parametrize docker-compose image pull - docker

I have a docker-compose yaml that looks like the following:
version: '3'
services:
my-service:
image: xxxx.dkr.ecr.eu-central-1.amazonaws.com/yyyy:latest
It pulls the latest image of a docker in ecr. I want to slightly change it to
version: '3'
services:
my-service:
image: xxxx.dkr.ecr.eu-central-1.amazonaws.com/yyyy:${tag}
that is, to be able to pass a tag parameter when I do the build. Is it possible to do this?

You can use a .env file in the same directory where your docker-compose.yaml is located or you pass it to the cli like tag=latest docker-compose up.
Example .env file:
tag=latest

Related

docker-compose override not taking additional yml into account?

docker-compose.yml:
version: '3.7'
services:
db:
image: mysql:8.0
docker-compose.test.yml:
version: '3.7'
services:
db:
ports:
- 3306:3306
docker-compose config does not show the port. Why?
I'm trying to display the effective compose file, means: the merge result that is also used by docker-compose up.
docker-compose version 1.25.0
According to the documentation, docker-compose will only automatically find files named docker-compose.yml and docker-compose.override.yml:
By default, Compose reads two files, a docker-compose.yml and an optional docker-compose.override.yml file. By convention, the docker-compose.yml contains your base configuration. The override file, as its name implies, can contain configuration overrides for existing services or entirely new services.
If you want to use additional compose files, you need to specify them explicitly using -f <filename>:
docker-compose up -f docker-compose.yml -f docker-compose.test.yml
By default, docker-compose finds the docker-compose.yml file. The problem you are facing is happening because the port is configured in the other file and DockerCompose doesn't know anything about it. If you want to check the configuration of the other file, you need to pass it as a parameter:
docker-compose -f ./path/to/docker-compose.test.yml config
Or you can put the port configuration on the first file like this:
version: '3.7'
services:
db:
image: mysql:8.0
ports:
- 3306:3306
And it should work just fine.

docker-compose - COMPOSE_PROJECT_NAME, DockerHub and "service name". How to use it?

I'm using docker-compose to built customised nginx and php images and then I'd like to push it to DockeHub.
I'm using COMPOSE_PROJECT_NAME in an .env file to set a prefix image name:
COMPOSE_PROJECT_NAME=myapp
and docker-compose.yml is something like:
version: '3'
services:
php-fpm:
build:
context: ./php-fpm
args:
.....
volumes:
.....
expose:
.....
nginx:
build:
context: ./nginx
args:
.....
volumes:
.....
port:
.....
Running docker-compose up -d the images name are:
myapp_nginx
myapp_php-fpm
the container name are:
myapp_nginx_1
myapp_php-fpm_1
Now, to push these images to DocekeHub I need to change image name adding the DockerHub "account" suffix:
myaccount/myapp_nginx
myaccount/myapp_php-fpm
to solve this problem, I added the "image" option to docker-compose.yml:
version: '3'
services:
php-fpm:
build:
context: ./php-fpm
args:
.....
volumes:
.....
expose:
.....
image: myaccount/${COMPOSE_PROJECT_NAME}_php-fpm
nginx:
build:
context: ./nginx
args:
.....
volumes:
.....
port:
.....
image: myaccount/${COMPOSE_PROJECT_NAME}_nginx
now, running docker-compose push the images are pushed to DockerHub.
Ok, my question are:
1) is there a way to insert DockerHub account name myaccout into COMPOSE_PROJECT_NAME variable? Something like: COMPOSE_PROJECT_NAME=myaccount/myapp to create automatically the image name like: myaccount/myapp_nginx and myaccount/myapp_php-fpm?
2) is there a variable to get "service name" the retrieve the name nginx or php-fpm?
For example, into the docker-compose.yml file, I could set: image: myaccount/${COMPOSE_PROJECT_NAME}_<service_name> then If I change the "service name" from nginx to nginx2 automatically the image will be myaccount/myapp_nginx2
3) is there a way to rename the images produced with docker-compose only to permit the push?
Thank you
You'd typically use fixed image names in this context. A published image name shouldn't be dependent on details of the specific Compose file that launched it.
version: '3'
services:
nginx:
build: ./nginx
image: myaccount/nginx # no project name
Imagine you're planning to run this same setup on a different system. It has Docker and Compose installed, but none of your application source code. You should be able to copy the docker-compose.yml file there, delete the build: line, and run the same thing. It doesn't matter if the directory is named project or other, and it doesn't matter if the Compose setup actually names the service proxy instead of nginx; you'd use the same image: to refer to it.
# COMPOSE_PROJECT_NAME=other
version: '3'
services:
proxy:
image: myaccount/nginx # same image as above
If you're unhappy with the names Compose produces, you can manually docker tag and docker push the images outside of Compose. You'll also need to do this if you want an image to have multiple tags (both a date stamp and latest for example) or if for whatever reason you need to push it to multiple repositories (both Docker Hub and Amazon ECR).

Re-using variables in docker-compose yml

There are two articles describing using environment variable but my use case is different.
I have docker-compose file where I have 3-7 containers. Depends on situation.
version: '2'
services:
db:
image: example/db
backend:
image: example/server
frontend:
image: example/gui
Now, in above example all my images will use latest version, but I would like to control which version to deploy, therefore I want to define some variable version and use it in all my images, something like:
version: '2'
variable version=1.0.1
services:
db:
image: example/db:$version
backend:
image: example/server:$version
frontend:
image: example/gui:$version
Second example is wrong, but it shows my need what I want to achieve
In the same directory as docker-compose.yml add an environment file named .env, then specify your environment variable.
After that, add variable into your docker-compose.yml
The ${..} represents a variable in .env
Docker-compose used Interpolation Syntax ${variable} for variables and you missed that in your file.
version: '2'
services:
db:
image: example/db:${version}
backend:
image: example/server:${version}
frontend:
image: example/gui:${version}
So just pass the version to your docker-compose command
version=1.13-alpine docker-compose up

Docker-compose specify tags from env file

I have docker-compose.yml like below:
version: '2'
services:
micro-service:
image: some/micro-service:${SERVICE_VERSION}
env_file:
- ../all-variables/${PROFILE}/micro_service.env
ports:
- "8085:8085"
And I have two files : dev.env and stage.env where SERVICE_VERSION and PROFILE are described.
Is there any way to specify concrete file when running docker-compose up
By default docker-compose takes .env file from current dir.
Is there a way to override it or another workaround ?
As mentioned in the answer in the comments there is no way to do that as it is directly coded into the source code to use .env.
However, there a couple ways to get similar behaviour.
The first way works natively with docker-compose, which would be to use docker-compose override files.
So in your case you could have your base docker-compose.yml file like this:
version: '2'
services:
micro-service:
image: some/micro-service:1.0.0
ports:
- "8085:8085"
Then you can define a docker-compose-dev.yml file:
version: '2'
services:
micro-service:
image: some/micro-service:dev
env_file:
- ../all-variables/dev/micro_service.env
Then you can run the following command
$ docker-compose up -f docker-compose.yml -f docker-compose-dev.yml up
If you do this the values in docker-compose-dev.yml will override those in docker-compose.yml. So instead of using image some/micro-service:1.0.0 it will use the image defined in docker-compose-dev.yml.
The second way would be to use docker-app. Which is a new experimental utility from the Docker team.
Basically you will create a dockerapp file that would look like this:
version: 0.0.1
name: app
---
version: '2'
services:
micro-service:
image: some/micro-service:${SERVICE_VERSION}
env_file:
- ../all-variables/${PROFILE}/micro_service.env
ports:
- "8085:8085"
---
SERVICE_VERSION: latest
PROFILE: default
Then if you convert your .env files to .yml render the compose file with the correct variables using docker-app.
docker-app render -f dev.yml | docker-compose -f - up
Hopefully this is helpful, I am going through a similar issue when working with multiple environments with docker-compose.

How to pass variables from a .env file to Docker?

I have a .env file with a large list of variables in the root of my node project. In the root is also my docker-compose.yml file:
version: '3'
services:
api:
build: .
env_file:
- .env
ports:
- 5000:5000
I'm trying to pass in these variables to Docker (from here), but when I run docker-compose up, I'm running into an error in my node app because it doesn't have access to these variables. What am I doing wrong? Thanks.
Change the file name to something different like node.env. The .env file is used by the docker-compose itself to define the content of the docker-compose file itself.
Example:
$ cat .env
TAG=v1.5
$ cat docker-compose.yml
version: '3'
services:
web:
image: "webapp:${TAG}"
The content of this file is not used inside the docker instance itself.

Resources