3

I have two elastic-beanstalk environments on AWS: development and production. I'm running a glassfish server on each instance and it is requested that the same application package be deployable in production and in development environment, without requiring two different .EAR files.The two instance differ in size: the dev has a micro instance while the production has a medium instance, therefore I need to deploy two different configuration files for glassfish, one for each environment.

The main problem is that the file has to be in the glassfish config directory before the server starts, therefore I thought it could be better moving it while the container was created.

Of course each environment uses a docker container to host the glassfish instance, so my first thought was to configure an environment variable for the elastic-beanstalk. In this case

ypenvironment = dev

for the development environment and

ypenvironment = pro

for the production environment. Then in my DOCKERFILE I put this statement in the RUN command:

    RUN if [ "$ypenvironment"="pro" ] ; then \
        mv --force /var/app/GF_domain.xml /usr/local/glassfish/glassfish/domains/domain1/config/domain.xml ; \
    elif  [ "$ypenvironment"="dev" ] ; then \
        mv --force /var/app/GF_domain.xml.dev /usr/local/glassfish/glassfish/domains/domain1/config/domain.xml ; \
    fi

unfortunately, when the startup finishes, both GF_domain files are still in var/app.

Then I red that the RUN command runs things BEFORE the container is fully loaded, maybe missing the elastic-beanstalk-injected variables. So I tried to move the code to the ENTRYPOINT directive. No luck again, the container startup fails. Also tried the

ENTRYPOINT ["command", "param"]

syntax, but it didn't work giving a

System error: exec: "if": executable file not found in $PATH

Thus I'm stuck.

2 Answers 2

2

You need:

1/ Not to use entrypoint (or at least use a sh -c 'if...' syntax): that is for runtime execution, not compile-time image build.

2/ to use build-time variables (--build-arg):

You can use ENV instructions in a Dockerfile to define variable values. These values persist in the built image.
However, often persistence is not what you want. Users want to specify variables differently depending on which host they build an image on.

A good example is http_proxy or source versions for pulling intermediate files. The ARG instruction lets Dockerfile authors define values that users can set at build-time using the --build-arg flag:

$ docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 .

In your case, your Dockefile should include:

ENV ypenvironment

Then docker build --build-arg ypenvironment=dev ... myDevImage

You will build 2 different images (based on the same Dockerfile)


I need to be able to use the same EAR package for dev and pro environments,

Then you want your ENTRYPOINT, when run, to move a file depending on the value of an environment variable.

Your Dockerfile still needs to include:

ENV ypenvironment

But you need to run your one image with

docker run -x ypenvironment=dev ...

Make sure your script (referenced by your entrypoint) includes the if [ "$ypenvironment"="pro" ] ; then... you mention in your question, plus the actual launch (in foreground) of your app.
Your script needs to not exit right away, or your container would switch to exit status right after having started.

Sign up to request clarification or add additional context in comments.

3 Comments

Sorry, it was not clear, but two different builds is what I'm trying to avoid. I need to be able to use the same EAR package for dev and pro environments, but inside elastic-beanstalk you can only deploy an EAR file, which in turn must contain the DOCKERFILE. Maybe there is a way to get the environment variable value in the context where the docker build command is run, but I don't know. I'll edit my question asap, thanks!
@Gabber So you are talking about runtime, not build time (Dockerfile)?
@Gabber I have edited my answer to include the runtime syntax
2
+50

When working with Docker you must differentiate between build-time actions and run-time actions. Dockerfiles are used for building Docker images, not for deploying containers. This means that all the commands in the Dockerfile are executed when you build the Docker image, not when you deploy a container from it.

The CMD and ENTRYPOINT commands are special build-time commands which tell Docker what command to execute when a container is deployed from that image.

Now, in your case a better approach would be to check if Glassfish supports environment variables inside domain.xml (or somewhere else). If it does, you can use the same domain.xml file for both environments, and have the same Docker image for both of them. You then differentiate between the environments by injecting run-time environment variables to the containers by using docker run -e "VAR=value" when running locally, and by using the Environment Properties configuration section when deploying on Elastic Beanstalk.

Edit: In case you can't use environment variables inside domain.xml, you can solve the problem by starting the container with a script which reads the runtime environment variables and puts their values in the correct places in domain.xml using sed, then starts your application as usual. You can find an example in this post.

5 Comments

This is not what I asked for, but what I needed. Thanks :)
Sorry, I tried this solution but didn't work, I'm afraid it's not possible to make the Glassfish domain.xml file to read the variables from the aws environment, thus can't accept this as the correct answer
Then there is another solution exactly for these cases. I've updated my answer. Good luck :-)
I've checked the solution (not yet tested), but I'm not sure if I understood it correctly. I have one doubt: inside the dockerfile I've put a command to copy a file or another based on an environment variable. I have tried both the ENTRYPOINT and the RUN commands for this script. This didn't work because the environment variables were not yet set. Why should the 'sed' command get the values if the 'if' statement couldn't? I think the problem here is that the env variables are not yet set when I run the command, so I'm afraid this wouldn't work
@Gabber, I'm talking about using run time env vars (docker run -e "MYVAR=myvalue") in conjunction with a startup script (which should be set using ENTRYPOINT or CMD). The startup script will do something like sed -i 's/foo/$MYVAR/g' domain.xml.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.