replace placeholders properties in spring/tomcat docker image - docker

I have a Dockerfile such as:
FROM tomcat:8.5
COPY webapp.war /usr/local/tomcat/webapps/
COPY conf /usr/local/tomcat/conf/
CMD ["catalina.sh", "run"]
conf contains many types of files (.json, .xml, .properties) with some placeholders in them with the following format: ${some.place.holder}
I want to build the image with the placeholders, and give to my users the possibility to replace them.
Ideally, when running the image, they should be able to give a new file as a parameter such as:
some.place.holder=hello
What would be the correct way to achive that?

If you want to use a bash file to set all the variables, you can write set_env_var.sh:
#!/bin/sh
export PLACEHOLDER1=value
export PLACEHOLDER2=value
And run:
source set_env_var.sh
It will set all the variables.
Or you can run any command by setting multiple variables like this. Eg. I want to run a docker-compose command with variables in it by:
PLACEHOLDER1=value PLACEHOLDER2=value docker-compose up -d

Related

how to open a file and read contents inside the Dockerfile

I have a docker file where i need to open a file and get the data .If the data is dev, i am passing a argument(dev application) and if it is not passing another argument(prod application)to the sh file. It should be something like
f=open config.txt
data=f.read()
if data=dev
app=dev application
else
app=prod application
ENTRYPOINT ["./entry.sh app"]
here i am trying to pass the argument to the .sh file (entry.sh).so i can use the incoming argument in the entry.sh file. Please help me how to do it in a correct way.
I am new to this Dockerfile.
You can pass arguments while building the docker image by using the ARG parameters like this. while building you can pass values like docker build --build-arg ENV_ARG=dev
DOCKER FILE CODE SAMPLE
ARG ENV_ARG=prod
ENV ENVIRONMENT=$ENV_ARG
CMD ["sh", "-c", "entry.sh ${ENVIRONMENT}"]

Replace an ENV variable inside a .sh file

I have a deadly doubt, I would like to replace an environment variable that is declared in a .sh file inside a docker image.
Any way to do this without having to mount a volume to change it?
NB. I already tried to do this through compose, and I have already guaranteed that my set variable is there, but it is overwritten by the original declaration inside the sh file.
I don't understand reason for such thing. ENV is gets exact value on a stage of image run. If you are trying to run multiple application with different profile pass different env file during docker run.
In Dockerfile you could pass argument to you shell script:
CMD my_app.sh ${APP_ADDR} ${APP_PORT}
in my_app.sh
get variables like
APP_ADDR=$1
APP_PORT=$2
and when you running you docker image store all you variables in env file and pass it like this:
docker run --env-file=app_local.env my_app:0.1
in env file you could define you variables:
APP_ADDR=192.168.200.200
APP_PORT=5678
....
You can do as suggested here
ENTRYPOINT ./base_image_entrypoint_script.sh && export URI=http://localhost
This way you override the base image ENTRYPOINT with the same script but will add the env car you wanted that will override the script variable.

How can I add a file to a volume in a Docker image, using values from the docker-compose.yml?

I have this .env file:
admin=admin
password=adminsPassword
stackName=integration-demo
the values of which are used in the docker-compose.yml file, like this:
myService:
build:
context: .
dockerfile: myService.Dockerfile
args:
- instance=${stackName}.local
- admin=${admin}
- password=${password}
volumes:
- ./config:/config
I want to add them to the Docker compose file, like this:
FROM openjdk:8-jdk-alpine
ARG docker_properties_file=Username=$admin\nPassword=$password\nHost=$instance
RUN $docker_proprties_file >> config/gradle-docker.properties
so that I have a gradle-docker.properties file that looks like:
username=admin
password=adminsPassword
host=integration.demo.local
in the /config directory.
However, no gradle-docker.properties file is getting written.
How can I use the variable in a docker-compose.yml file to add data to a volume?
Plain Docker and Docker Compose don’t have this capability. You can create the file outside of Docker on the host and mount it into the container as you show, but neither Docker nor Compose has the templating capability you would need to be able to do this.
The overall approach you’re describing in the question builds a custom image for each set of configuration options. That’s not really a best practice: imagine needing to recompile ls because you attached a USB drive you needed to look at.
One thing you can do in plain Docker is teach the image how to create its own configuration file at startup time. You can do that with a script like, for example:
#!/bin/sh
# I am docker-entrypoint.sh
# Create the config file
cat >config/gradle-docker.properties <<EOF
username=$USERNAME
et=$CETERA
EOF
# Run the main container process
exec "$#"
In your Dockerfile, COPY this file into the image and set it as the ENTRYPOINT; leave your CMD unchanged. You must use the JSON-array form of the ENTRYPOINT directive.
...
COPY docker-entrypoint.sh .
RUN chmod +x docker-entrypoint.sh
ENTRYPOINT ["./docker-entrypoint.sh"]
CMD ["java", "-jar", "application.jar"]
(In Kubernetes, the Helm package manager does have a templating system that can create content for a ConfigMap object that can be injected into a pod; but that’s a significant amount of extra machinery.)

ECS Container Environment Configuration

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

Docker: modify files during image creation

I'm creating a Docker image for Atlassian JIRA.
Dockerfile can be found here: https://github.com/joelcraenhals/docker-jira/blob/master/Dockerfile
However I want to enable the HTTPS connector on the Tomcat server inside the Docker image during image creation so that the server.xml file is configured during image creation.
How can I modify a certain file in the container?
Best regards,
Alternative a)
I would say you are going the wrong path here. You do not want to do this during image creation, but rather during the entrypoint.
It is very common and best practise in docker to configure the service during the first container start e.g. seed the database, generate passwords and seeds and, as in you case, generate configuration based on templates.
Usually those configuration files are either controlled by ENV variables you pass on to docker run or rather in your docker-compose.yml, in more complex environments the source of the configuration variables can be consul or etcd.
For your example, e.g. you could introduce a ENV variable 'USE_SSL' and then either use sed in your entrypoint to replace something in the server.xml when it is set, but since you need much more, like setting the revers_proxy domain and things, you should go with tiller : https://github.com/markround/tiller
Create a server.xml.erb file, place the variables you want to be dynamic, use if conditions if you want to exclude a section if USE_SSL is not set, and let tiller use ENVIRONMENT as a datasources.
Alternative b)
If you really want to stay with the "on image build" concept ( not recommended ) you should use the so called build_args https://docs.docker.com/engine/reference/commandline/build/
Add this to your docker file
ARG USE_SSL
RUN /some_script_you_created_to_generate_server_xml.sh $USE_SSL
You still need to have a bash/whatever script some_script_you_created_to_generate_server_xml.sh which takes the args, and creates by conditions, whatever you want. Tiller though will be much more convenient when stuff gets bigger (compared to running some seds/awks)
and then, when building the image, you could use
`docker build . --build-arg USE_SSL=no -t yourtag
You need to extend this image with your custom config file, write your own Dockerfile with following content:
FROM <docker-jira image name>:<tag>
COPY <path to the server.xml on your computer, relative to Dockerfile dir> <path to desired location of server.xml inside the container>
After that you need to build and run your new image:
docker build . --tag <name of your image>
docker run <name of your image>

Resources