Generally, a docker container is meant to hold exactly one application. For a typical Java web application (in this example we assume a Tomcat 8 servlet container and a Postgres 9.4 database), this will lead to two and a half containers:
- The
webcontainer for our web application (in the example we assume.WARpackaging) deployed to Tomcat - The
dbcontainer for our Postgres database - The
db-datacontainer. This one is necessary because Docker containers are volatile by default. Thus, data stored in a container is lost when they are restarted, so we need a volume to permanently store the database data.
Naturally, the applications within their respective containers need to communicate with each other. The current tool of choice to enable inter-container communication is Docker Compose.
Directory and file structure
The directory structure for our Docker files looks like this:
project
│ docker-compose.yml
│
└───db
│ Dockerfile
│
├───web
│ Dockerfile
│ application.war
The database container
We will begin with the Dockerfile of our database in ./db/Dockerfile:
FROM postgres:9.4
MAINTAINER lpradel
ENV POSTGRES_USER admin
ENV POSTGRES_PASSWORD password
ENV POSTGRES_DB app_staging
In this example we are using the standard Postgres 9.4 image and configure credentials for a single user and DB.
The application container
The Dockerfile for our web container in ./web/Dockerfile looks like this:
FROM tomcat:8-jre8
MAINTAINER lpradel
RUN echo "export JAVA_OPTS=\"-Dapp.env=staging\"" > /usr/local/tomcat/bin/setenv.sh
COPY ./application.war /usr/local/tomcat/webapps/staging.war
CMD ["catalina.sh", "run"]
The image is based on the standard Tomcat 8 image. I have included an example of how to perform basic Tomcat configuration. Here, we pass some JAVA_OPTS to the setenv.sh shell script of Tomcat.
Finally, our application .WAR is copied the to the Tomcat webapps directory and deployed in the staging context.
Docker Compose
The last step is orchestrating our containers in ./docker-compose.yml:
app-web:
build: ./web
ports:
- "8081:8080"
links:
- app-db
app-db:
build: ./db
expose:
- "5432"
volumes_from:
- app-db-data
app-db-data:
image: cogniteev/echo
command: echo 'Data Container for PostgreSQL'
volumes:
- /var/lib/postgresql/data
We bind the default Tomcat port 8080 in the container to the 8081 port of our host system and expose the Postgres port 5432 to the web container which is linked to it. Lastly, we reference the permanent data volume as a volume for our db container.
Running the application
Execute the following command to start our containers:
$ docker-compose up -d
To stop the containers run
$ docker-compose stop
A list of all docker containers is available via
$ docker ps -a
To open a shell in one of the containers (for example to access log files), run the following command:
$ docker exec -it <container_id> /bin/bash
Finally, to redeploy only specific containers, use the following command:
$ docker-compose build <container_id>
$ docker-compose up --no-deps -d <container_id>