Dockerizing Tomcat and Postgres with Fig
Let me share some thoughts on how one can use Docker and Fig to run custom webapps in Tomcat and Postgres.
Tools that we are using
- Docker - Gives ability to run any App in a container
- Fig - helps run a combined setup of few Docker containers
- boot2docker - sets up special Virtual Machine and gives ability to run Docker on Mac OS X
- Tomcat - Java app server
- PostgreSQL - SQL Database
What do we want
We want:
- run a custom set of Java webapps
- custom Tomcat configuration
- simulate development environment
- Webapps are pre-configured to talk with DB on localhost
- in Docker
Installing tools
- On Mac OS X, download the latest boot2docker distribution and install it.
- install Fig with
pip install -U fig
Configuring
We will use a custom Tomcat docker, that will pre-install postgresql-client
and socat
. The socat
is used for forwarding a local port 5432 to the remote address. Her’s our Dockerfile
:
FROM tomcat:7
RUN apt-get update && apt-get install -y curl postgresql-client socat
Next, create the fig.yml
:
web:
build: .
volumes:
- tomcat:/usr/local/tomcat
- startTomcatAll.sh:/start.sh
command: "sh /start.sh"
links:
- db
ports:
- "8080:8080"
db:
image: "postgres:9.4"
ports:
- "5432:5432"
volumes:
- postgres:/data
Some info:
build
tells Fig to build a custom Docker container, and specifies where theDockerfile
isvolumes FROM:TO
maps folder from the host OS, into the guest container. In our case, we have atomcat
folder which contains the config and the webapps, and a custom start script.command
executes the custom script upon start. NOTE: The last command should output something, or Fig will stop the container.tail -f catalina.out
will do the job.links
tells what other containers shoul be linked. You will also get the environment variables likeDB_PORT_5432_TCP
, which we will use in our script.ports
tells what ports to map from container into host OS.image
tells what public image from Docker Hub to use.
The start.sh
script will look like this:
#!/bin/sh
# Port forwarding: localhost:5432 -> $DB_PORT_5432_TCP:5432
env | grep DB_PORT_5432_TCP= | sed 's/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/' | sh
# Check the DB connection by listing tables
psql -h localhost -U postgres -l
# Some scripts rely on the operating system...
echo "Ubuntu" > /etc/issue
# Start the custom Tomcat
startTomcat.sh
# Output the log, so Fig can catch this
tail -f /usr/local/tomcat/bin/catalina.out
A side note about Postgres container
A PostgreSQL official Docker container is set to be run from a user postgres
. In Mac OS X the volumes
are mounted with a current Mac user.
If we will mount a volume that contains the binary database files, when a container starts, Postgres will crash, because the username that is used to run a postgres does not match the username that the database files are.
The possible way to overcome is to tar
the files and “untar” them on start of a container.
The other way is to import the SQL dump - psql -f /data/all_dbs.sql -h localhost -U postgre
.
If you are on the Mac, you might want to tell boot2docker
VM to forward the 5432
port to your Mac. to do so, run
VBoxManage modifyvm "boot2docker-vm" --natpf1 "tcp-port5432,tcp,,5432,,5432";
Starting up
If you’r on a Mac, make sure the boot2docker VM is started - boot2docker start
. Next, make sure that the environment is properly set by running $(boot2docker shellinit)
.
Run fig up
and watch the Fig will start the db
and web
containers and outputs the log into the console. You could run docker build .
to build your Dockerfile
, but fig will do it for you.
Now you can open your browser on localhost:8080
and see your Tomcat app.
You can connect to any container from other shell by running docker exec -i -t test_web_1 bash
(or _db_1
)
Cleanup
docker images
will list all images (-a
will list all)docker ps
will list running containers (-a
for all)fig rm
will remove all stopped containersdocker images -f dangling=true -q |xargs docker rmi -f
- will remove all dangling (not-named) Docker images