I previously played around with MongoDB in a few containers. Recently, I tried IBM Db2 Community Edition and learnt a few new things about containers along the way. The challenge was rolling my own Db2 Data Server Manager container, working around the background process that the startup script kicks off.

Danger: Learn from me, but don’t do what I do.

Starting Db2

This is the easy part.

First, create a new virtual network for the containers to communicate.

docker network create myDBnet

Then, get the Db2 Community Edition image and start it. Suggest you read the info in the previous link and the Quick Start on DockerHub, which explains the arguments below. Note that the database files will be created in the current folder ($PWD):

mkdir db2
cd db2
docker run -it -d --name mydb2 --privileged=true -p 50000:50000 -e LICENSE=accept -e DB2INST1_PASSWORD=password -e DBNAME=testdb -v "$PWD":/database --network myDBnet ibmcom/db2

As Db2 is starting up, you may run docker logs -f mydb2 to check the log. You’ll see info under the heading Database Connection Information, followed a bit later by (*) All databases are now active confirming your instance is created and running.

Now, you can run an interactive shell on the running container, to run the Db2 CLI. To do that docker exec -it mydb2 bash -c "su - db2inst1", then:

db2 list db directory
db2 connect to testdb

Building Db2 Data Server Manager

This was the tough part, since I wanted to use the downloaded Db2 Data Server Manager free edition installer to create a new image via a Dockerfile.

Well, I could’ve saved the effort and used the official Data Server Manager image on DockerHub. But where is the fun in that?

First, download ibm-datasrvmgr-linux-x86_64.tgz into a directory of your choosing - no need to extract from the .tgz archive. Note the download link requires an IBM login.

Then in that same directory, run this to create a Dockerfile. It’ll then create a new docker image by extracting the downloaded archive, editing the setup.conf file and running the setup.sh script silently:

cat > Dockerfile << EOF
FROM centos:7
ADD ibm-datasrvmgr-linux-x86_64.tgz /usr
WORKDIR /usr/ibm-datasrvrmgr
RUN sed -i -e "s/^#product./product./" -e "s/^#admin.user/admin.user/" -e "s/^#admin.password=.*/admin.password=password/" setup.conf && ./setup.sh -silent 
RUN echo -e '#!/bin/sh\n/usr/ibm-datasrvrmgr/bin/start.sh\ncat' > run.sh && chmod +x run.sh
ENTRYPOINT [ "/usr/ibm-datasrvrmgr/run.sh" ]
EOF
docker build -t db2_dsm .
docker run -it -d --name=mydsm -p 11080:11080 -p 11081:11081 -p 11082:11082 --network myDBnet db2_dsm

Building actually starts the service - far from ideal, but that’s the way the setup.sh script is coded.

I configured the setup file with a static username and password. Please don’t do this. At least use to use tool /usr/ibm-datasrvrmgr/dsutil/bin/crypt.sh to encrypt the password.

I tried RUN sed -i -e "s/^#product./product./" -e "s/^#admin.user/admin.user/" -e "s/^#admin.password=.*/admin.password=$(/usr/ibm-datasrvrmgr/dsutil/bin/crypt.sh password)/" setup.conf && ./setup.sh -silent, but this did not produce the expected results. I don’t know why.

To recap - run creates a new container and runs a given command. Stop it with docker stop mydsm, and re-start with docker start mydsm. To delete the container, docker rm mydsm. To delete the image docker rmi db2_dsm. Similarly for the db2 container mydb2. If you don’t like background process, remove -d from both docker run above. In that case, stop the container with Ctrl-C.

If you see something similar to this in the logs (docker logs -f mydsm), then all is good:

docker logs -f mydsm
Starting server dsweb.
DSM SERVER STATUS: ACTIVE
Server dsweb is running with process ID 164.

Background process do not keep container running

When I initially started the container, it would stop after a minute or so. Ah, found out that Docker containers need a foreground process in order to keep running. The start up script above starts the Data Server Manager in the background... and once the script ends, Docker promptly stops the container!

One suggestion at StackOverflow was to keep Bash running with a TTY in the background (e.g. docker run -t -d centos), but this did not work for me. Also tried with and without interactive mode (-i).

So I experimented with other suggestions from StackOverflow, most required adding some never ending task to the startup script. I admit there are nuances that I may not understand so here is a summary of options:

  • sleep infinity (does not work in MacOS, does not work for containers using Busybox), or
  • a looping sleep as a workaround, while :; do sleep 2073600; done, or
  • just letting cat keep waiting, or
  • anything similar (although please don’t use tail -f /dev/null as it causes a busy loop).

So, I decided create a new script to call the startup script and then run cat. I could’ve also edited the startup script itself, by replacing the last two lines in the Dockerfile with:

RUN echo cat >> /usr/ibm-datasrvrmgr/bin/start.sh
ENTRYPOINT [ "/usr/ibm-datasrvrmgr/bin/start.sh" ]

As I tried these options, I found it useful to quickly get into a new temporary container just to play around docker run -it --rm -p 11080:11080 --network myDBnet --entrypoint bash db2_dsm.

Usage

Open your browser to localhost:11080 and login as admin / password.

Drop down the connections combo box (that says “No existing connections”) and hit Connections. Click on Add > Add a database. Then configure it like below, remember to check Enable operation and in the next tab, Credential enter the user ID db2inst1 and password password:

IBM Db2 Data Server Manager connecting to Db2 in containers

FYI: You’ll notice I refer to the Db2 container hostname as the container name specified with --name. If you run docker network inspect myDBnet you’ll find two hostnames and IP addresses assigned.

BTW I tried the new Db2 Data Management Console but had issues with the silent install and even after that could not connect to Db2. Too lazy to solve this!

Anyway, good luck!