I have a docker-compose file which includes the following:
environment:
DOCUMENT_ROOT: /var/some/dir
I would like to add that path to my container.
In my DockerFile I add:
RUN echo "export PATH=$PATH:${DOCUMENT_ROOT}" >> /root/.bashrc
But it doesn't work. It seems the ENV parameter isn't available.
What's the problem ?
Yaron
ARG some_variable_name
RUN echo "export PATH=$PATH:${some_variable_name}" >> /root/.bashrc
You should use ARG in Dockerfile and set arguments in build command:
docker build --build-arg some_variable_name=a_value
ARG is only available during the build of a Docker image (RUN etc),
not after the image is created and containers are started from it
(ENTRYPOINT, CMD). You can use ARG values to set ENV values to work
around that.
or in docker-compose:
version: '3'
services:
somename:
build:
context: ./app
dockerfile: Dockerfile
args:
some_variable_name: a_value
Understanding Docker Build Args, Environment Variables and Docker Compose Variables
Related
How to pass environment variables to RUN command in Dockerfile? In my scenario, I want to pass env variables to RUN command which runs a script & uses these variables?
.env
NAME=John
script.sh
#!/bin/sh
echo $NAME
Dockerfile
FROM alpine:3.14
COPY . .
RUN chmod +x script.sh
RUN ./script.sh
docker-compose.yml
version: "3.1"
services:
foo:
container_name: foo
build:
context: .
dockerfile: Dockerfile
restart: unless-stopped
How can I pass the NAME env variable to the last RUN command in Dockerfile (to be used by the script executable)?
I am aware of --build-arg but it is inconvenient when there are 100s of env variables. Even then how can I format the docker compose command to read all arguments from an env file & pass them as build arguments?
I have:
docker-compose.yml
version: "3.9"
services:
test_name:
image: ${PROJECT_NAME}/test_service
build:
dockerfile: Dockerfile
env_file: .env
Dockerfile
FROM alpine:3.15
RUN echo $TEST >> test1.txt
CMD echo $TEST >> test2.txt
As result:
test1.txt - empty and test2.txt with data.
My problem is that this variables are too much, so can I get environment variables in RUN command from .env file without enumeration all of them in ARG?
To use variables in a RUN instruction, you need to use ARG. ARG are available at build time while ENV is available when the container runs.
FROM alpine:3.15
ARG FOO="you see me on build"
ENV BAR="you see me on run"
RUN echo $FOO >> test1.txt
CMD echo $BAR >> test2.txt
docker build --build-arg FOO="hi" --tag test .
docker run --env BAR="there" test
There is one thing that comes close to using env variables, but you still need to provide the --build-arg flag.
You can define env variable with the same name as the build arg and reference it by its name without setting a value. The value will be taken from the env variable in your shell.
export FOO="bar"
docker build --build-arg FOO --tag test .
This also works in compose.
Additionally, when you use compose you can place a .env file next to your compose file. Variables found there will be read and are available in the build:arg key as well as the environment key, But you still have to name them.
# env file
FOO=bar
BAZ=qux
services:
test_name:
build:
context: ./
args:
FOO:
BAZ:
I have a docker-compose.yml that has a section:
myservice:
env_file:
- myvars.env
My env variable file has:
myvars.env:
SOME_VAL=123
And then in my Dockerfile I have this:
..
RUN echo "some_val ${SOME_VAL}"
ENTRYPOINT bash ${APP_BASE}/run.sh SOME_VAL=${SOME_VAL}
When I run docker-compose up, the value of some_val is empty.
Why is SOME_VAL not accessible in my dockerfile?
How do I pass the env variable SOME_VAL to my run.sh script?
You need to declare the variable with ENV in the Dockerfile before using it:
ENV variables are also available during the build, as soon as you introduce them with an ENV instruction.
Dockerfile
ENV SOME_VAL
RUN echo "some_val ${SOME_VAL}"
ENTRYPOINT bash ${APP_BASE}/run.sh SOME_VAL=${SOME_VAL}
When you docker-compose build an image, it only considers the build: sections of the docker-compose.yml file. Nothing else from any other part of the file is considered. environment: and env_file: settings aren't available, nor are volumes: nor networks:. The only way to pass settings in is through the Dockerfile ARG and the corresponding Compose args: settings, and even then, you only want to use this for things you'd "compile in" to the image.
Conveniently, shell scripts can directly access environment variables already, so you don't need to do anything at all; just use the variable.
#!/bin/sh
# run.sh
echo "SOME_VAL is $SOME_VAL"
# Dockerfile
FROM busybox
WORKDIR /app
COPY run.sh .
# RUN chmod +x run.sh
CMD ["./run.sh"]
# docker-compose.yml
version: '3.8'
services:
echoer:
build: .
env_file:
- my_vars.env
# environment:
# SOME_VAL: foo
I'm trying to use args in a docker compose file.
The docker-compose file:
version: '3'
services:
service1:
image: test
restart: always
build:
context: C:/ProgramData/
dockerfile: Dockerfile
args:
entry: 1
volumes:
- C:/ProgramData/test
The Dockerfile:
FROM microsoft/dotnet-framework:3.5
ARG entry
WORKDIR C:\\test
ADD ["/bin/x86/Release/","C:/test/"]
ENTRYPOINT ["C:\\test\\file.exe", ${entry}]
I don't know how exactly works the syntax in the docker file. How I have to put the arg in the ENTRYPOINT?
You cannot use ARG in ENTRYPOINT (at least not directly). See How to pass ARG value to ENTRYPOINT?:
Both ARG and ENV are not expanded in ENTRYPOINT or CMD. (https://docs.docker.com/engine/reference/builder/#environment-replacement) However, because ENVs are passed in as part of the environment, they are available at run time, so the shell can expand them. (This means you can't use the array form of ENTRYPOINT or CMD.)
I solved this issue by changing the Dockerfile as follows:
FROM microsoft/dotnet-framework:3.5
ARG ENTRY
ENV my_env=$ENTRY
#RUN echo %ENTRY%
#RUN echo %my_env%
WORKDIR C:\\test
ADD ["/bin/x86/Release/","C:/test/"]
ENTRYPOINT C:/test/file.exe %my_env%
How can I pass a host environment variable (like user and hostname) to a dockerfile?
For example, if my username is taha:
echo $USER
taha
How do I write my Docker file to get the same output?
FROM centos:centos7
ARG myuser=$USER
CMD echo $myuser
I was experiencing the same issue. My solution was to provide the variable inside of a docker-compose.yml because yml supports the use of environment variables.
In my opinion this is the most efficient way for me because I didn't like typing it over and over again in the command line using something like docker run -e myuser=$USER . . .
Declaring ENV myuser=$USER will NOT work, in the container, $myuser will be set to null.
So your docker-compose.yml could look something like this:
version: '3'
services:
app:
build:
context: .
dockerfile: Dockerfile
environment:
- "myuser=${USER}"
and can be run with the short command docker-compose up
To check that the variable has been applied, run docker exec -it container-name printenv to list all variables in the container.
When you start your docker container you can pass environment variables using the -e option like so:
docker run -it <image> -e USER=$USER /bin/bash
I had a similar use-case where I wanted to be able to specify a version for the image. This has a slight extra requirement that you must specify the ARG before the FROM.
First we specify IMAGE_VERSION in the Dockerfile, as per the question I'm also including a USER arg that we can pass in too:
# give it a default of latest
# declare the ARG before FROM
ARG IMAGE_VERSION=latest
FROM centos:${IMAGE_VERSION}
ARG myuser
CMD echo $myuser
Then, as from the Docker compose docs on args:
Add build arguments, which are environment variables accessible only during the build process.
You can add these in your docker-compose.yml for example:
version: '3'
services:
app:
build:
context: .
dockerfile: Dockerfile
args:
"myuser=${USER}"
IMAGE_VERSION
Then as long as you have IMAGE_VERSION set in your environment it will be passed through.
you need to use the ENV setting in your dockerfile
ENV myuser=$USER
https://docs.docker.com/engine/reference/builder/#env