This question already has answers here:
Using dollar symbol in docker compose build args confusion
(1 answer)
How to evaluate a dynamic variable in a docker-compose.yml file?
(2 answers)
Closed last month.
Can I use dynamic generated values in docker-compose.yml file like in the code below?
version: "3"
services:
php:
build:
context: ./.docker-config/dockerfiles
dockerfile: php.dockerfile
args:
- HOST_UID=${id -u}
- HOST_GID=${id -g}
- HOST_USER=${whoami}
volumes:
- ./:/var/www/html:delegated
...and in the php.dockerfile:
ARG HOST_UID
ARG HOST_USER
RUN useradd $HOST_USER -u $HOST_UID
It says:
ERROR: Invalid interpolation format for "build" option in service "php": "HOST_UID=${id -u}"
I think now the parameter passed into container contains this string: ${id -u} and not the value of the expression.
Can I somehow pass in the result of the expression?
You can set the variables as environment variables on your docker-compose build command, like this
HOST_UID=$(id -u) HOST_GID=$(id -g) HOST_USER=$(whoami) docker-compose build
Then you need to change your docker-compose file to get the values from the environment variables, like this
args:
- HOST_UID=${HOST_UID}
- HOST_GID=${HOST_GID}
- HOST_USER=${HOST_USER}
It's not as user-friendly as having the commands in the docker-compose file, of course.
Here's how I tested it:
docker-compose.yml
version: '3'
services:
app:
build:
context: .
args:
- HOST_UID
- HOST_GID
- HOST_USER
Dockerfile:
FROM debian
ARG HOST_UID
ARG HOST_GID
ARG HOST_USER
RUN echo ${HOST_UID}
RUN echo ${HOST_GID}
RUN echo ${HOST_USER}
Build command:
HOST_UID=$(id -u) HOST_GID=$(id -g) HOST_USER=$(whoami) docker-compose build --no-cache
Related
Use case is to build and image and deploy to Rancher 2.5.5 with gitlab-ci.yml. Since envs couldn't be passed directly in my situation I'm trying to build-in envs to docker image with docker-compose build (dev/stage things is the next thing, just let's leave it for now). docker-compose run --env-file works, but docker-compose build ignores envs.
Any advice will be appreciated
P.S. if you know the way to pass envs to rancher2 container somehow from gitlab-ci it also resolves the problem
I've tried the following:
set it in docker-compose
version: '3'
services:
testproject:
build:
context: .
env_file: .env-dev
image: example.registry/testimage:latest
set it in gitlab-ci
variables:
IMAGE: "$CI_REGISTRY_IMAGE:latest"
build-image:
stage: build
allow_failure: false
tags:
- docker
services:
- docker:dind
script:
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
- docker-compose --env-file .env-dev build
- docker-compose push
deploy:
stage: deploy
image: kpolszewski/rancher2-gitlab-deploy
tags:
- docker
script:
- upgrade --cluster $CLUSTER --environment $ENV --stack $NAMESPACE --service $SERVICE --new-image $IMAGE
source it in Dockerfile entrypoint
set it in .env file
nothing works
I can see new image in the registry and local (when I test it locally ) but no env inside when I run container
If you want to set env values on the build stage, you can use build-args as follows:
FROM ...
ARG SOME_ARG
ENV SOME_ENV=$SOME_ARG
Then, in your docker-compose.yml:
version: '3'
services:
testproject:
build:
context: .
args:
SOME_ARG: "SOME_VALUE"
env_file: .env-dev
image: example.registry/testimage:latest
But think twice, are you sure you want your ENV variables be dynamically set on the build stage?
Suppose that I type the following command
docker-compose -f docker-compose.yml build --build_args PARAM=1
How should I write my docker-compose.yml such that the yml fiel gets the argument PARAM, whose value is 1?
My yml file is below.
version: '3.7'
services:
web:
build:
context: .
dockerfile: ./Dockerfile
args:
- MY_PARAM: ${PARAM}
ports:
- "5000:5000"
image: sample-img:1.0
I added
args:
- MY_PARAM: ${PARAM}
below build. Is this correct?
Here is how you can pass build arguments while using compose -
Allow arguments support in Dockerfile.
FROM foo:bar
ARG PARAM
ARG PARAM2
.................
Now you can pass these arguments in two different ways -
During runtime -
docker-compose -f docker-compose.yml build --build-arg "PARAM=1 PARAM2=2"
Within compose using shell -
$ export PARAM=1 PARAM2=2
Change docker compose as below -
dockerfile: ./Dockerfile.foo
args:
PARAM: ${PARAM}
PARAM2: ${PARAM2}
Build it -
$ docker-compose -f docker-compose.yml build
I have the following in my docker-compose.yml file
geth-testnet:
build:
context: .
dockerfile: Dockerfile
args:
GETH_REPO: 'https://github.com/ethereum/go-ethereum'
GETH_VERSION: 'v1.8.12'
RPC_LISTEN_PORT: 8546
command: "--rpcport ${RPC_LISTEN_PORT}"
entrypoint:
- "geth"
tty: true
image: geth-node-testnet:v1.8.12
container_name: geth-node-testnet
ports:
- '8546:8546'
volumes:
- /root/.ethereum
When I run, docker-compose up --build, expect it to run the following command:
geth -rpcport 8546
However, I get the following error
flag needs an argument: -rpcport
So, the value for RPC_LISTEN_PORT is not correctly substituted.
I have ARG RPC_LISTEN_PORT in my dockerfile
Double checked your question, seems command: "--rpcport ${RPC_LISTEN_PORT}" cannot utilize the value you put in docker-compose.yml.
So afford two solutions:
export RPC_LISTEN_PORT=8546 in bash before you do compose command.
New a .env file in the same folder, put RPC_LISTEN_PORT=8546 to it.
I have written a Dockerfile which uses two arguments:
FROM jessie
MAINTAINER Zeinab Abbasimazar
#Build Arguments
ARG REP_USER
ARG REP_PASS
# Build
RUN echo 'REP_USER:'$REP_USER', REP_PASS:'$REP_PASS
I wrote a docker-compose.yml for build:
version: "2"
services:
ui:
build:
context: .
dockerfile: Dockerfile
args:
REP_USER: $REP_USER
REP_PASS: $REP_PASS
I don't want to define these arguments directly in the compose file, so I tried to send them during docker compose build:
REP_USER=myusername REP_PASS=mypassword docker-compose build
Which didn't work. I changed my Dockerfile to use these arguments as environment variables; so I removed ARG lines:
FROM jessie
MAINTAINER Zeinab Abbasimazar
# Build
RUN echo 'REP_USER:'$REP_USER', REP_PASS:'$REP_PASS
And docker-compose.yml:
version: "2"
services:
ui:
build:
context: .
dockerfile: Dockerfile
And ran REP_USER=myusername REP_PASS=mypassword docker-compose build; still no result.
I also tried to save these information into an env file:
version: "2"
services:
ui:
build:
context: .
dockerfile: Dockerfile
env_file:
- myenv.env
But it seems env files doesn't affect at build time; they are just take part into run time.
EDIT 1:
Docker version is 1.12.6 which doesn't support passing arguments with --build-arg.
EDIT 2:
I tried using .env file as described here:
cat .env
REP_USER=myusername
REP_PASS=mypassword
I then called docker-compose config which returned:
networks: {}
services:
ui:
build:
args:
REP_PASS: mypassword
REP_USER: myusername
context: /home/zeinab/Workspace/ZiZi-Docker/Test/test-exec-1
dockerfile: Dockerfile
version: '2.0'
volumes: {}
Which means this resolved my issue.
EDIT 3:
I also tried third section of docker-compose arg documentation in my docker-compose.yml file:
version: "2"
services:
ui:
build:
context: .
dockerfile: Dockerfile
args:
- REP_USER
- REP_PASS
And executed:
export REP_USER=myusername;export REP_PASS=mypassword;sudo docker-compose build --no-cache
Still not getting what I wanted.
You can set build arguments with docker compose as described here:
docker-compose build [--build-arg key=val...]
docker-compose build --build-arg REP_USER=myusername --build-arg REP_PASS=mypassword
Btw, AFAIK build arguments are a compromise between usability and deterministic building. Docker aims to build in a deterministic fashion. That is, wherever you execute the build the produced image should be the same. Therefore, it appears logical that the client ignores the environment (variables) it is executed in.
The correct syntax for variable substitution in a docker-compose file is ${VARNAME}.
Try with this one:
version: "2"
services:
ui:
build:
context: .
dockerfile: Dockerfile
args:
REP_USER: ${REP_USER}
REP_PASS: ${REP_PASS}
I finally found the solution. I mentioned it in the question too. I first tried it with fail, then I found out that I had a typo naming .env file; it was .evn.
I tried using .env file as described here:
cat .env
REP_USER=myusername
REP_PASS=mypassword
I then called docker-compose config which returned:
networks: {}
services:
ui:
build:
args:
REP_PASS: mypassword
REP_USER: myusername
context: /home/zeinab/Workspace/ZiZi-Docker/Test/test-exec-1
dockerfile: Dockerfile
version: '2.0'
volumes: {}
Which means this resolved my issue. I should mention that this answer was really helpful.
On my image I want to set some environment variables eg: MY_VAR where it will have a static value eg: MY_VAR=12 but I do NOT want to be able to set it via docker's -e param or via docker-compose.yml's environment section.
Furthermore I do not want to be as build argument when i do either docker build or docker-compose build
How can I do that?
You can do that from an entrypoint script.
In your Dockerfile:
ENTRYPOINT ["/entrypoint.sh"]
Example entrypoint.sh:
#!/bin/sh
export VAR=foobar
exec /usr/bin/python "$#"
To be more flexible and allow setting it with the -e option:
export VAR=${VAR:-"foobar"}
...
The best solution for your question is to include an env_file on your docker-compose build
version: '3.2'
services:
db:
restart: always
image: postgres:alpine
volumes:
- backup-data:/var/lib/postgresql/data
env_file:
- ./env/.dev
Then in your env_file:
POSTGRES_USER=my_user
POSTGRES_PASSWORD=my_password
POSTGRES_DB=my_db