After reading the config point of the 12 factor app I decided to override my config file containing default value with environment variable.
I have 3 Dockerfiles, one for an API, one for a front-end and one for a worker. I have one docker-compose.yml to run those 3 services plus a database.
Now I'm wondering if I should define the environment variables in Dockerfiles or docker-compose.yml ? What's the difference between using one rather than another ?
See this:
You can set environment variables in a service’s containers with the 'environment' key, just like with docker run -e VARIABLE=VALUE ...
Also, you can use ENV in dockerfile to define a environment variable.
The difference is:
Environment variable define in Dockerfile will not only used in docker build, it will also persist into container. This means if you did not set -e when docker run, it will still have environment variable same as defined in Dockerfile.
While environment variable define in docker-compose.yaml just used for docker run.
Maybe next example could make you understand more clear:
Dockerfile:
FROM alpine
ENV http_proxy http://123
docker-compose.yaml:
app:
environment:
- http_proxy=http://123
If you define environment variable in Dockerfile, all containers used this image will also has the http_proxy as http://123. But the real situation maybe when you build the image, you need this proxy. But, the container maybe run by other people maybe not need this proxy or just have another http_proxy, so they had to remove the http_proxy in entrypoint or just change to another value in docker-compose.yaml.
If you define environment variable in docker-compose.yaml, then user could just choose his own http_proxy when do docker-compose up, http_proxy will not be set if user did not configure it docker-compose.yaml.
Related
How to using env variables in Dockerfile?
not args
This is my Dockerfile now:
FROM node:12
I want Dockerfile:
FROM node:$version
How can I do it? If it is not possible, then I will create a feature request for Docker.
You need to add as ARGs under a different place from the ENV variables. You can use them in the compose, just a little differently.
ARGs will be used during the build only, if you need them to available for the build & again while running the container for some reason you will have to set both an ARG as well as an ENV variable. {{{During the Build stage they will be called in the exact same manner}}}. ENV are set to replace defaults when running a container, so the build's ENV TZ=Europe/London will be replaced by the Compose's Environment: TZ=America/New_York
services:
my_node_version:
image: my/node
build:
context: .
dockerfile: ../node.Dockerfile
args:
- VERSION=12
- NEEDED_IN_BUILD_AND_RUN=SomeStrangeUseCase
environment:
- ONLY_USED_IN_IMAGE=MyImageWorks
- NEEDED_IN_BUILD_AND_RUN=SomeStrangeUseCase
- OVERRIDE_BUILD_ENV="Will replace the ENV from the Build"
I'm pretty sure that fulfills all the intent from the question (you asked to not use args I assume because you wanted them set in the docker-compose.yaml rather than the dockerfile). You can do this, you just have to set them in a different way.
ENV cannot be used in the build from the Compose (ENV variables set in the Dockerfile just set the defaults that the container will use if none are declared in the OS, the Compose, or anywhere Docker gets them from), so that simply isn't a possibility, so if you need it to be ENV specifically for some reason then the answer is simply "You can't" end of discussion. But I don't see anything that could possibly accomplish, & no reason using ARGs wouldn't accomplish exactly what you want. You just need to place them in a different section, but they should function as needed
If I'm using Docker with nginx for hosting a web app, how can I use either
Variables in my docker-compose.yml file
Environment variables such as HOSTNAME=example.com.
So that when I build the container, it will insert the value into my nginx.conf file that I copy over when I build the container.
You can use environment variables is your compose file. According to official docs
Your configuration options can contain environment variables. Compose uses the variable values from the shell environment in which docker-compose is run. For example, suppose the shell contains POSTGRES_VERSION=9.3 and you supply this configuration:
db: image: "postgres:${POSTGRES_VERSION}"
When you run docker-compose up with this configuration, Compose looks for the POSTGRES_VERSION environment variable in the shell and substitutes its value in.
See the docs for more information. You will find various other approaches to supply environment variables in the link like passing them through env_file etc.
I have writte a docker-compose.yml file to create a multi-container app with nodejs and mongodb (so 2 containers), and I want to make some options configurable, as the choice of server address and port.
To do that, I have written what follows in docker-compose.yml to set them as env variables:
..
web:
environment:
- PORT=3000
- ADDRESS=xxx.xxx.xxx.xxx
..
Within the source code of my application, I use process.env.PORT and process.env.ADDRESS to refer to these variables.
But how can I do if I want to change those values, and for example set PORT=3001?
I have to use docker-compose build and docker-compose up again and build all the application, included mongodb container?
I have to use docker-compose build and docker-compose up again and build all the application, included mongodb container?
Not build, just up. They are runtime options, not build options. Changing them in the docker-compose.yml file and then doing a docker-compose up again should recreate the containers with the new environment variables.
Alternatively, you can specify environment variables outside the docker-compose.yml file to make for easier changes:
One of these methods is to use a .env file in the same folder that you execute docker-compose form (see https://docs.docker.com/compose/env-file/ for information on it).
Another option is to interpolate environment variables from your shell. You could specify them such as - PORT=${APP_PORT} and then export APP_PORT=3000 on your shell before running docker-compose. See https://docs.docker.com/compose/environment-variables/ for more information.
When running a number of linked services with docker-compose up, how can I add values for environment variables to be passed to specific containers for services? Say I have a service "webapp" which uses the TIMEOUT environment variable, how do I set TIMEOUT=10000 with docker-compose for the container that "webapp" lives in? I have tried the notation -e TIMEOUT=10000 from the docker command, but this does not seem to work.
with docker compose your have to specify environment variables in docker-compose.yml with env_file or environment configuration commands
https://docs.docker.com/compose/compose-file/#env-file
https://docs.docker.com/compose/compose-file/#environment
This might be a general docker problem but my use-case is docker-compose:
I need to pass my machine's hostname as an environment variable to a container which would be created through docker-compose. That particular container uses a Dockerfile and uses "cmd" flag in it. The command in "cmd" uses this environment variable. Can someone please help?
If you can rewrite the Dockerfile in order to include the hostname in an ENV instruction, as mentioned in issue 1136, that will work:
FROM centos:latest
ENV BLABLA hello
RUN echo $BLABLA
# outputs: "hello"
If this is purely a runtime environment variable value, it should be included in docker 1.9 with issue 14634: Builder - Build-time argument passing (e.g., HTTP_PROXY):
In the meantime, the OP 208rishabh mentions issue 2091 for docker compose, answered by dnephin:
environment or env_file should both work:
You can leave the value blank, and it will take the value from the current environment:
environment:
HOST_HOSTNAME:
That allows:
HOST_HOSTNAME=$(hostname) docker-compose up