Can i pass codeship env in docker build - docker

Can I pass the code ship env ex.CI_BRANCH to docker build. I'm must be use it to run bulid backpack separate build for staging or production by CI_BRANCH

There is currently no way to utilize the Codeship environment variables during the image build time.
You can however pass along these environment variables during run time with a step command:
command: /bin/bash -c './script_dependent_on_timestamp.sh $CI_TIMESTAMP'

Related

How to pass variable in a docker image at runtime that will be used by the automation test scripts

I have created a docker image of my test automation framework project (maven project). The automation test scripts gets the app url & credentials through a property file that resides inside the project. I have run the image and the automation test scripts executes properly (via pom.xml).
Now I want to pass the app url & credentials at runtime, as those may change based on environments. So is there a way I can pass these values at docker runtime and still my automation scripts will be able to run with these passed on values?
If you create a Dockerfile like
FROM ubuntu:latest
ENV envvar="default value"
CMD ["/bin/sh", "-c", "echo ${envvar}"]
you can override the environment variable when you run the container. If you run it with the command
docker run -e envvar=hello <image name>
it'll print out hello
You can pass them by using the parameters --env or --env-file to the `docker run command as explained at https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file .
As alternative you can map an external volume by the -v passed to the docker build command in order to inject external configuration files to the running docker container, as better explained at https://docs.docker.com/storage/volumes/ .

Set today's date as environment variable

I need to set today's date as environment variable in my docker container.
What I am trying to do is to get today's date so I can use it to call some API with Logstash's http_poller plugin.
The solution I am thinking about is to get today's date using the command date +%Y%m%d
How can I set the result of this command as an environment variable at run time?
ARG should be what you are looking for:
FROM base
# to be able to use in Dockerfile
ARG now
# to store the value as environment variable in the image
ENV build_date=$now
Now you can build this with
# pass value explicitly
docker build --build-arg now="$(date +%Y%m%d)" .
# pass value from environment
export now="$(date +%Y%m%d)"
docker build --build-arg now .
This still requires to run date on the host since doing this inside the Dockerfile is not possible unfortunately:
The only way to execute arbitrary commands in the build is within a RUN statement; but
The only way to persist a variable into the environment of an image/container is with an ENV statement which can only use environment variables from outside the build
You could use a custom ENTRYPOINT tough and inject the date to the environment from a file:
FROM base
RUN date +%Y%m%d > /build-timestamp
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT /entrypoint.sh
entrypoint.sh:
#!/bin/bash
export BUILD_TIMESTAMP="$(cat /build-timestamp)"
exec "$#"
So according to your answer to my comment, if you want to have the variable set at runtime you need to inject it when you start your container
✗ docker run -e TS=$(date +%Y%m%d) python:3.7-alpine env
TS=20201230
PYTHON_VERSION=3.7.9
HOME=/root
Here is the link to the docker documentation : https://docs.docker.com/engine/reference/run/#env-environment-variables
But you are confusing the Dockerfile with the container. A Dockerfile is a definition for building an image. This image is static. Then you start multiples containers from this base image.
So if your start 3 containers with the same image, according to your question you expect 3 different dates in your containers. So you see why you can't set a date or a command in a Dockerfile. The previous snippet does what you ask.
According to the documentation ENV only supports <key>=<value> entries, I see no way to put it there with a command. I suggest you drop the value into some file then read it when needed. Or, if you have a launch script, using RUN you can add export VAR_NAME=<value> to the launch script so that the variable is automatically added to the environment on launch.
My solution was to first do export command and then running service startup like this
CMD export INSTALL_DATE=$(date +%s) && python3 /product/server.py

How to set different ENV variable when building and deploying Docker Image to Cloud Run?

I have a backend service that I'll need to deploy to Google Cloud Run.
From Google's tutorial on Cloud Run, we get that:
First you need to build your image and send it to Cloud Build.
gcloud builds submit --tag gcr.io/PROJECT-ID/helloworld
Only then you deploy it to Cloud Run:
gcloud run deploy --image gcr.io/PROJECT-ID/helloworld --platform managed
I get the sequence above. But I'll be deploying this service to 2 different environments: TEST and PROD.
So I need an SERVER_ENV variable, that should be "PROD" on my production environment, and of course it should be "TEST" on my test environment. This is so my server (express server that will be run from the container) knows which database to connect to.
But the problem is that I only have a single Dockerfile:
FROM node:12-slim
ENV SERVER_ENV=PROD
WORKDIR /
COPY ./package.json ./package.json
COPY ./distApp ./distApp
COPY ./distService ./distService
COPY ./public ./public
RUN npm install
ENTRYPOINT npm start
So how can I set different ENV variables while following the build & deploy sequence above? Is there an option in the gcloud builds submit comment that I can maybe override something? Or use a different Dockerfile? Anybody got other ideas?
AN IDEA:
Maybe use the Cloud Build configuration file?
cloudbuild.yaml
You can't achieve this without a cloudbuild.yaml file. The command gcloud builds submit --tag ... doesn't accept extra docker parameter.
Here an example of configuration
FROM node:12-slim
ARG SERVER_CONF=PROD
ENV SERVER_ENV=$SERVER_CONF
WORKDIR /
COPY ./package.json ./package.json
COPY ./distApp ./distApp
COPY ./distService ./distService
COPY ./public ./public
RUN npm install
ENTRYPOINT npm start
I created a build argument SERVER_CONF. Your ENV will take this value at build time. The default value is PROD
Now your cloudbuild.yaml file
step:
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '--tag=gcr.io/PROJECT-ID/helloworld', '--build-arg="SERVER_CONF=$_SERVER_CONF"', '.']
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/PROJECT-ID/helloworld']
substitutions:
_SERVER_CONFPROD: PROD
Use substitution variables to change the environment. Not that here you can also set a default value, that override your Dockerfile value. Take care of this!
You can also set the tag as substitution variable if you want
Eventually, how to call your Cloud Build
# With default server conf (no substitution variables, the the file default)
gcloud builds submit
# With defined server conf
gcloud builds submit --substitutions=_SERVER_CONF=TEST
I think that what you are trying to achieve is possible using the ARG instruction in the Dockerfile.
I would set it to be test and then use the arg parameter according to the environment you are building in right now.
More docs:
how to use it with Docker Compose - https://docs.docker.com/compose/compose-file/#args
additional documentation - https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact

How to pass ENV variable to build process in Docker

Building a container for my Go application has trouble with Environment variables.
On my local machine, I can do the following:
export GIN_MODE=release
go build -a
This will compile my application in a way, where the library called GIN will notice the GIN_MODE env-variable and behave differently.
When I run the application, it will state
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
if this ENV-variable was not set and it will omit this warnings, if the GIN_MODE variable was set properly.
However, in Docker it won't work that way.
In my Dockerfile I wrote these specific code lines:
# Build the Go app
ENV GIN_MODE=release
RUN CGO_ENABLED=0 GOOS=linux go build -v -a -installsuffix cgo -o main .
I tried also to pass the variable directly in the RUN statement:
RUN GIN_MODE=release CGO_ENABLED=0 GOOS=linux go build -v -a -installsuffix cgo -o main .
The variable will never be visible to the go-build statement.
How can I achieve that?
Environment variables are not compiled into the go binary. Environment variables are properties of a process that get passed down to their child processes.
Your Dockerfile is correctly setting the GIN_MODE environment variable. But this Dockerfile appears to be used for building the go binary, but not for running/deploying the compiled binary. Thus, you should ensure that you also set the GIN_MODE environment variable for the execution context of the deployed application, whether that may be in a Dockerfile or a systemd unit or whatever else happens to be the method of deployment.
The reason why it "worked" when you did the go build manually in your shell was because your shell process carried the GIN_MODE environment variable by way of you running export GIN_MODE=release, and you used the same shell to later run the application, the GIN_MODE environment variable was available to your application by way of being a child process from your shell.

How to use environment variable from parent Docker file?

I have two Dockerfiles Dockerfile.A & Dockerfile.B where Dockerfile.B inherits using the FROM keyword from Dockerfile.A. In Dockerfile.A I set an environment variable that I would like to use in Dockerfile.B (PATH). Is this possible, and how would I go about doing it?
So far I have tried the following in Dockerfile.A:
RUN export PATH=/my/new/dir:$PATH
ENV PATH=/my/new/dir:$PATH
RUN echo "PATH=/my/new/dir:$PATH" >/etc/profile
And in Dockerfile.B, respectively:
Just use tools in the path to see if they were available (they were not)
ENV PATH
RUN source /etc/profile
I realized that every RUN command is executed in it's own environment, and that is probably why the ENV keyword exists, to make it possible to treat environments independently of the RUN commands. But I am not sure what that means for my case.
So how can I do this?
Works as expected for me.
Dockerfile.A
FROM alpine:3.6
ENV TEST=VALUE
Build it.
docker build -t imageA .
Dockerfile.B
FROM imageA
CMD echo $TEST
Build it.
$ docker build -t imageB .
Run it
$ docker run -it imageB
VALUE

Resources