Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using environment variable for volume name in docker compose

Tags:

I am using docker compose version 3.3 and want to use environment variable to define the volume name. I looked at a related question, but that seems to be quite old. With long syntax supported in 3.2, is there a way to achieve that? Here is what I tried in my docker compose file:

version: '3.3'
services:
  target:
    image: "my-registry/my-image:${IMAGE_TAG}"
    volumes:
        - type: volume
          source: ${VOLUME_NAME}
          target: /data
    ports:
     - "${TOMCAT_PORT}:8080"

volumes:
  ${VOLUME_NAME}:

Obviously this syntax does not work as volume name is not substituted in the keys and throws the following error:

volumes value Additional properties are not allowed ('${VOLUME_NAME}' was unexpected)

Any help will be much appreciated.

like image 723
Aarkan Avatar asked Jul 14 '17 13:07

Aarkan


People also ask

Can you use environment variables in Docker compose?

Docker Compose allows us to pass environment variables in via command line or to define them in our shell. However, it's best to keep these values inside the actual Compose file and out of the command line. “Why?” you may ask.

How do I name a docker volume?

Declaring and referencing a named volume in a docker-compose file will create an empty volume which may then be accessed and shared by the services saying so in their volumes section. If you want to share a named volume, you have to declare this volume in the top-level volume section of your docker-compose file.

Does Docker compose override environment variables?

But docker-compose does not stop at the . env and the host's current environment variables. It's cool that you can simply override values of your . env file, but this flexibility is can also be the source of nasty bugs.

How do I pass environment variables to docker containers?

With a Command Line Argument The command used to launch Docker containers, docker run , accepts ENV variables as arguments. Simply run it with the -e flag, shorthand for --env , and pass in the key=value pair: sudo docker run -e POSTGRES_USER='postgres' -e POSTGRES_PASSWORD='password' ...


2 Answers

This is expected behavior - Compose only does variable interpolation in values, not keys. See here.

In my project I use external structure:

version: '3.1'
services:
### Code from branch develop ###
  applications:
    image: registry.gitlab.lc:5000/develop/ed/develop.sources:latest
    volumes:
      - developcode:/var/www/develop
    deploy:
      replicas: 1
      update_config:
        parallelism: 1
        delay: 5s
      restart_policy:
        condition: on-failure
      placement:
        constraints: [node.role == manager]
### PHP-FPM ###
  php-fpm:
    image: registry.gitlab.lc:5000/develop/ed/php-fpm-ed-sq:latest
    volumes:
      - developcode:/var/www/develop
    expose:
      - "9000"
    deploy:
      replicas: 2
      update_config:
        parallelism: 1
        delay: 5s
      restart_policy:
        condition: on-failure
      placement:
        constraints: [node.role == manager]
    logging:
      driver: gelf
      options:
        gelf-address: "udp://${GRAYLOG_ADDR}:12201"
        tag: "php-fpm"
### Nginx ###
  nginx:
    image: registry.gitlab.lc:5000/develop/ed/nginx-ed-sq:staging
    volumes:
      - developcode:/var/www/develop
    ports:
      - "80:80"
      - "443:443"
    deploy:
      replicas: 2
      update_config:
        parallelism: 1
        delay: 5s
      restart_policy:
        condition: on-failure
      placement:
        constraints: [node.role == manager]
### Volumes Setup ###
volumes:
  developcode:
    external:
      name: code-${VER}

but first of all I need create external volume manually, e. g.:

export VER=1.1 && docker volume create --name code-$VER

You can see created volume:

docker volume ls
DRIVER              VOLUME NAME
local               code-1.0
local               code-1.1

And after that, deploy services using:

env $(cat .env | grep ^[A-Z] | xargs) docker stack deploy --with-registry-auth --compose-file docker-compose.yml MY_STACK
like image 73
Yevhen Lebid Avatar answered Sep 29 '22 19:09

Yevhen Lebid


If you want to avoid conflicts between different projects, you just need to specify --project-name "your_project_name" for docker-compose. It adds namespace for all services and volumes.

For example, you may use the same docker-compose.yml for few projects:

volumes:
    dbdata_mysql:

services:
    mysql_db:
        image: mysql:5.7
        volumes:
            - "dbdata_mysql:/var/lib/mysql"

If you starts your projects with:

docker-compose --project-name "first_project" up -d
docker-compose --project-name "second_project" up -d

it will create namespaced volumes:

$ docker volume ls | grep dbdata_mysql

local     first_project_dbdata_mysql
local     second_project_dbdata_mysql
like image 35
IStranger Avatar answered Sep 29 '22 19:09

IStranger