Specifying --build-args inside a DockerFile's FROM - docker

My DockerFile:
FROM puckel/docker-airflow
...
# rest of file
Looking at the source DockerFile of puckel/docker-airflow, I see there are several args that can be configured at build time, which I want to do:
# contents of puckel/docker-airflow
...
# Airflow
ARG AIRFLOW_VERSION=1.10.6
ARG AIRFLOW_USER_HOME=/usr/local/airflow
ARG AIRFLOW_DEPS=""
ARG PYTHON_DEPS=""
I know I can set these args using docker build and adding the flag(s), for example docker build --build-arg AIRFLOW_VERSION=1.11 ... for example, but how can I set these args within my DockerFile itself?

This isn't possible. When you build FROM another image, you are building from the result of a previous build. The parent image has already been created, and the ARGs have already been used. You have to rebuild the parent image with different args if you want changes applied there.
Note that build args are scoped, they only exist within the build stage (or Dockerfile for global args), and are not directly available to be used in child images.

Related

Common content of two Dockerfiles

I have a docker configuration that I want to run both locally and on the CI (Github).
The only difference in the Dockerfiles is the FROM directive:
local configuration uses Nexus (behind firewall)
CI configuration uses Github Container Registry (GHCR)
Rest of the configuration is exactly the same (base images are the same images, just pulled from different source).
Now the majority of Dockerfile content and files that are copied into image need to be duplicated in both env specific directories.
I'd like to have common Dockerfile configuration in case of any changes needed.
Current state example:
local/Dockerfile:
FROM nexus.example.com/myapp/app:latest
{several lines of code}
ci/Dockerfile:
FROM ghcr.io/mycompanyapp:latest
{the same several lines of code as above}
Desired:
common/Dockerfile:
{common code}
local/Dockerfile:
FROM nexus.example.com/myapp/app:latest
# INCLUDE ../common/Dockerfile
ci/Dockerfile:
FROM ghcr.io/mycompanyapp:latest
# INCLUDE ../common/Dockerfile
I am aware of existence of the edrevo/dockerfile-plus but I am looking for more official solution. It was tedious to link Dockerfile residing in different directory than build context.
Also it seems that it is not maintained actively and it may not work on Windows which is used by other team members (issue https://github.com/edrevo/dockerfile-plus/issues/27)
You can use ARGS do to this.
ARG REPO=nexus.example.com
FROM ${REPO}/app:latest
....
So the default config will be nexus.example.com and in your CI you just need to build with arg REPO=something
example:
docker build -t myapp:latest --build-args REPO=ghcr.io -f Dockerfile
For local build:
docker build -t myapp:latest -f Dockerfile

Retrieving a CI variable from Gitlab project and use it within Dockerfile

I have a CI variable that I would like to use within my docker file. I have tried to include it such as
ENV TESTING_UNIT=$TESTING_ID
It seems like that you need to specify to Dockerfile that it expects an argument variable
With the following approach it will be available in the container
Change:
ENV TESTING_UNIT=$TESTING_ID
To:
ARG TESTING_UNIT_ARG
ENV TESTING_UNIT=$TESTING_UNIT_ARG
and build the image: docker build --build-arg TESTING_UNIT_ARG=$TESTING_ID

define a locale environment variable in Dockerfile

Is there any way to create local variables in Dockerfile that only available during the build process? What I can see is if I define a variable with the ENV keyword, then it will be available later in the image as an exported environment variable. But I would like to have a "technical" variable with build scope only.
I would like to avoid repetition in my Doclerfile so I would like to have a variable available only from the Dockerfile:
ENV MY_JAR=myJar.jar
COPY bin/$MY_JAR $ORACLE_HOME/user_projects/domains/$DOMAIN_NAME/lib/
COPY bin/$MY_JAR $ORACLE_HOME/wlserver/server/lib/mbeantypes/
But the MY_JAR variable appears in the container. I do not need it there. It just confuses users. Can I do this somehow?
Use ARG instead of ENV
ARG MY_JAR=myJar.jar # ARG is only available during the build of a Docker image
COPY bin/$MY_JAR $ORACLE_HOME/user_projects/domains/$DOMAIN_NAME/lib/
COPY bin/$MY_JAR $ORACLE_HOME/wlserver/server/lib/mbeantypes/
see also ARG or ENV, which one to use in this case?
You can use the --build-arg parameter to pass environment variables that lives just during docker building process.
So your docker build command will look something like this
docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 -t sample:v1 .
Where HTTP_PROXY is just available during the build process.

How to specify build-time ENVs in docker-compose.yml

Both ARGs an ENVs are available to a Dockerfile at build time, but apparently Docker Compose allows only to specify ARGs in service.build.args. ENVs specified in service.environment apparently are not visible at build time (which also makes sense given this path).
So if my build depends on ENVs (as well as ARGs) and if I build with docker-compose build, how can I provide the build-time ENVs inside my docker-compose.yaml?
There's no way to externally pass environment variables into a Dockerfile, whether via docker build or the Compose build: block. You can only specify arguments.
If you really need to specify an environment variable at build time, you can pass it as an argument and then set the environment variable in the Dockerfile
ARG FOO
ENV FOO ${FOO}
You must rebuild the image if you ever change one of these things. That makes this technique not work well for deployment-specific settings like user IDs, host names, etc. It's also okay for container-side port numbers and filesystem paths to be fixed properties of the image.

How can the current build context directory be referenced inside of a Dockerfile?

I'm trying to set an environment variable to the current build directory inside of a Dockerfile. For example, I'm trying to do something like this:
ENV APP_SRC $BUILD_CONTEXT # Save the current host directory to an env variable
COPY . /$APP_SRC # Copy the app source code to a directory of the same name in the container
I know it sounds like a weird thing to do, but I need my directory name to be the same in the container as it is on my host machine. Is this possible?
With docker 1.9, you can pass build-time environment variable:
docker build --build-arg APP_SRC=$BUILD_CONTEXT -y tag .
$APP_SRC will then be valued like $BUILD_CONTEXT.
Note that this is not yet supported by docker compose: both issue 2111 and 2163 are asking for that feature.

Resources