Is there a way to refer a label (in current Dockerfile or inherited labels) in a Docker file? For example lets say I want to have a Dockerfile like below
FROM nginx
LABEL firstlabel="first label"
LABEL secondlabel="I want to use value of ${firstlabel}"
where I want to use the value of label "firstlabel" in the secondlabel. Is that possible? I tried using the ${} variable but it is not working.
You can use build arguments and environment variables to do this kind of thing.
You should be aware though that there are two phases for every container i. e. building and running. Labels defined in a Dockerfile are associated to an image so are generally set at build time although you can set/overwrite labels on docker run using --label <label-name>=<label-value> option. So passing a value for an environment variable that is used within a label to docker run will not update that label as the label is set on build time.
Consider the following Dockerfile:
FROM alpine
# build argument of name buildDate
ARG buildDate
# environment variables for author name
ENV AUTHOR_FNAME=John \
AUTHOR_LNAME=McClain
# we can use both in our labels
LABEL testlabel="Author: ${AUTHOR_FNAME} ${AUTHOR_LNAME}"\
buildDate=${buildDate}
Now build the container and provide the build arguments:
docker build -t test/test --build-arg buildDate=$(date +'%Y-%m-%d') .
Run the container:
docker run --name test -it --rm test/test sh
No open up another Terminal session and use the following command to inspect the labels:
docker inspect test --format='{{json .Config.Labels}}'
Result:
{"buildDate":"2022-04-28","testlabel":"Author: John McClain"}
You can now type exit into to sh to leave the container and it will automatically be removed.
Related
I am trying to label my docker image with my app version from within my Dockerfile using the LABEL command.
I can write the version into a file with the following:
RUN /opt/app/foo --version > /var/app-version
/var/app-version would now contain a plaintext file with the application version inside, ready for use in my label.
Now I need a way to place this into a docker variable/arg such that I can do something like the following:
LABEL application_version=$APP_VERSION
Or perhaps there is another way to achieve the same?
You're not going to be able set a label using content generated dynamically from something installed inside the container. You can set a label dynamically from your host environment using a build argument, like this:
FROM docker.io/alpine:latest
ARG application_version=1
LABEL application_version=${application_version}
If I build the container like this:
docker build -t myimage .
I will have:
$ docker inspect image myimage | jq '.[0].Config.Labels'
{
"application_version": "1"
}
Whereas if I build the container like this:
docker build --build-arg application_version=3 -t myimage .
I will have:
$ docker inspect image myimage | jq '.[0].Config.Labels'
{
"application_version": "3"
}
If you use the same build argument value to select the version of the
software you install in your container, you can ensure that the
installed version and the label match.
I'm managing a GitLab CICD pipeline which builds Docker images in a couple of stages and now I want to include in each Docker image a label with git's commit hash (see label-schema's vcs-ref label).
I've noticed that GitLab already provides convenient env variables with that info (see CI_COMMIT_SHA and CI_COMMIT_SHORT_SHA in GitLab CI/CD environment variables) but I have no idea of how to include the info provided in those env variables in a Docker image. Does anyone know if it's possible to include git's commit hash in a label?
You need to pass the commit as a build argument.
For example, in the Dockerfile:
ARG CI_COMMIT_SHA
LABEL git-commit=$CI_COMMIT_SHA
And when you build:
docker build --build-arg CI_COMMIT_SHA .
If you don't supply a variable, e.g. --build-arg CI_COMMIT_SHA=abc123 then it will use the local environmental variable of the same name.
In your Dockerfile, use LABEL
LABEL commit_sha=YOUR_CI_COMMIT_SHA
LABEL commit_short_sha=YOUR_CI_COMMIT_SHORT_SHA
Use docker inspect to get the labels from the images
docker inspect --format='{{.Config.Labels.commit_sha}}' image:tag
I need to set some environment variables in a docker container after it starts. When the docker starts env X gets value, then I want to set env Y with a value which is the first part of the value X with this command:
Y=$(echo $X | cut -d'#' -f 1)
Is there any way to do this?
I tried ENTRYPOINT and CMD in the Dockerfile, but it doesn't work.
The docker will be deployed on a Kubernetes cluster, and I also tried to set them in the config.yaml file but it doesn't work either.
You are on the right track that you would have to handle this by either CMD or ENTRYPOINT, because you want it to be dynamic and derived from existing data. The specifics would depend on your container and use case though.
You can use the ENV command in your dockerfile like below:
ENV PORT 8080
Source and more info - https://vsupalov.com/docker-build-time-env-values/
I have a docker-compose.yml set up like this:
app:
build:
dockerfile: ./docker/app/Dockerfile.dev
image: test/test:${ENV}-test-app
...
Dockerfile called here has this line present:
...
RUN ln -s ../overrides/${ENV}/plugins ../plugins
...
And there is also a script I am running to get the whole environment up (it is dependant upon several containers so I tried to omit irrelevant info).
It is a bash script and running the following:
ENV=$1 docker-compose -p $1 up -d --force-recreate --build app
What I wanted to achieve is that i can run two app containers at the same time, and this works as follows:
sh initializer.sh foo -> creates foo-test-app container
sh initializer.sh bar -> creates bar-test-app container
Now the issue I'm having is that even when I have --force-recreate flag present two images created actually are seen as the same image with two different tags.
And what this does when I inspect the containers is that both containers have a symbolic link to:
overrides/foo/plugins
It doesn't notice when I create the new container to re-do that part. How can I fix it?
Also if I sh to one container and change the symbolic link, it is automatically changed in the other container as well.
$ENV in your dockerfile is not the same as the one in your compose file.
When you run docker-compose up, it can be roughly seen as a docker build followed by a docker run. So Docker builds the image, layer by layer, at that stage there is not env called ENV. Only at docker run will $ENV be used.
Environment variables at build stage can be used though, they are passed via ARG
// compose.yml
build:
context: frontend
args:
- BUILD_ENV=${BUILD_ENV}
// dockerfile
ARG BUILD_ENV
RUN ./node_modules/.bin/ng build --$BUILD_ENV
You can do this to solve your problem however this will create one image per project, which you may not want. Or you can do it in an entrypoint script.
I have found the answer to be in project flag when creating my containers. So this is what I did:
docker-compose -p foo up -d
docker-compose -p bar up -d
This would bring containers up as 2 separate projects.
Link to documentation
I have a recently-Dockerized web app that I would like to get running on AWS ECS, and a few fundamental concepts (which I don't see explained in the AWS docs) are throwing me off.
First, when you Edit/configure a new container, it asks you to specify the image to use, but then also has an Environment section:
The Entry point, Command and Working directory fields look suspiciously similar to the commands I already specified when creating my Docker image (here's my Dockerfile):
FROM openjdk:8
RUN mkdir /opt/myapp
ADD build/libs/myapp.jar /opt/myapp
WORKDIR /opt/myapp
EXPOSE 9200
ENTRYPOINT ["java", "-Dspring.config=.", "-jar", "myapp.jar"]
So if ECS is asking me for an image (that's already been built using this Dockerfile), why in tarnation do I need to re-specify the exact same values for WORKDIR, EXPOSE, ENTRYPOINT, CMD, etc.?!?
Also outside of ECS I run my container like so:
docker run -it -p 9200:9200 -d --net="host" --env-file ~/myapp-local.env --name myapp myapp
Notice how I specify the env file? Does ECS support env files, or do I really have to enter each and every env var from my env file into this UI here?
Also I see there is a Docker Labels section near the bottom:
Are these different than env vars, or are they interchangeable?
Yes you need to add environment variable either through UI or through CLI .
For CLI you need to pass it as JSON template .
Also if you have already specified these values in Dockerfile then you dont need to pass these values again.
All the values that will be passed externally will overwrite internal/default values in Dockerfile