Wildfly Docker container connecting to separate MySQL container (Tutorial Part 2)


In this tutorial I will show how to set up a MySQL docker container for use by a separate Docker container running Wildfly Application Server. See part 1 of the tutorial on how to set up Docker and create a Wildfly container.

MySQL Docker image

Build a MySQL image based on Debian

Create a Dockerfile like the one below

FROM debian:stretch-slim

# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN groupadd -r mysql && useradd -r -g mysql mysql

RUN apt-get update && apt-get install -y --no-install-recommends gnupg dirmngr && rm -rf /var/lib/apt/lists/*

# add gosu for easy step-down from root
ENV GOSU_VERSION 1.7
RUN set -x \
 && apt-get update && apt-get install -y --no-install-recommends ca-certificates wget && rm -rf /var/lib/apt/lists/* \
 && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \
 && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \
 && export GNUPGHOME="$(mktemp -d)" \
 && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
 && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
 && rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc \
 && chmod +x /usr/local/bin/gosu \
 && gosu nobody true \
 && apt-get purge -y --auto-remove ca-certificates wget

RUN mkdir /docker-entrypoint-initdb.d

RUN apt-get update && apt-get install -y --no-install-recommends \
# for MYSQL_RANDOM_ROOT_PASSWORD
 pwgen \
# for mysql_ssl_rsa_setup
 openssl \
# FATAL ERROR: please install the following Perl modules before executing /usr/local/mysql/scripts/mysql_install_db:
# File::Basename
# File::Copy
# Sys::Hostname
# Data::Dumper
 perl \
 && rm -rf /var/lib/apt/lists/*

RUN set -ex; \
# gpg: key 5072E1F5: public key "MySQL Release Engineering <mysql-build@oss.oracle.com>" imported
 key='A4A9406876FCBD3C456770C88C718D3B5072E1F5'; \
 export GNUPGHOME="$(mktemp -d)"; \
 gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
 gpg --export "$key" > /etc/apt/trusted.gpg.d/mysql.gpg; \
 rm -rf "$GNUPGHOME"; \
 apt-key list > /dev/null

ENV MYSQL_MAJOR 5.7
ENV MYSQL_VERSION 5.7.21-1debian9

RUN echo "deb http://repo.mysql.com/apt/debian/ stretch mysql-${MYSQL_MAJOR}" > /etc/apt/sources.list.d/mysql.list

# the "/var/lib/mysql" stuff here is because the mysql-server postinst doesn't have an explicit way to disable the mysql_install_db codepath besides having a database already "configured" (ie, stuff in /var/lib/mysql/mysql)
# also, we set debconf keys to make APT a little quieter
RUN { \
 echo mysql-community-server mysql-community-server/data-dir select ''; \
 echo mysql-community-server mysql-community-server/root-pass password ''; \
 echo mysql-community-server mysql-community-server/re-root-pass password ''; \
 echo mysql-community-server mysql-community-server/remove-test-db select false; \
 } | debconf-set-selections \
 && apt-get update && apt-get install -y mysql-server="${MYSQL_VERSION}" && rm -rf /var/lib/apt/lists/* \
 && rm -rf /var/lib/mysql && mkdir -p /var/lib/mysql /var/run/mysqld \
 && chown -R mysql:mysql /var/lib/mysql /var/run/mysqld \
# ensure that /var/run/mysqld (used for socket and lock files) is writable regardless of the UID our mysqld instance ends up having at runtime
 && chmod 777 /var/run/mysqld \
# comment out a few problematic configuration values
 && find /etc/mysql/ -name '*.cnf' -print0 \
 | xargs -0 grep -lZE '^(bind-address|log)' \
 | xargs -rt -0 sed -Ei 's/^(bind-address|log)/#&/' \
# don't reverse lookup hostnames, they are usually another container
 && echo '[mysqld]\nskip-host-cache\nskip-name-resolve' > /etc/mysql/conf.d/docker.cnf

VOLUME /var/lib/mysql

COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 3306
CMD ["mysqld"]

Download this file and place it in the same directory. Then create the image by executing

sudo docker build -t j-lawyer-mysql-server .

This will give the image the name „j-lawyer-mysql-server“.

Start the image

Replace „secretpwd“ with a password to use for the MySQL root user.

sudo docker run --name j-lawyer-mysql-server -e MYSQL_ROOT_PASSWORD=secretpwd -d mysql:5.7

If you’d like to test the image using a MySQL command line client or to set up databases, execute

sudo docker run -it --link j-lawyer-mysql-server:mysql --rm mysql sh -c 'exec mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"$MYSQL_PORT_3306_TCP_PORT" -uroot -p"$MYSQL_ENV_MYSQL_ROOT_PASSWORD"'

This way, you can create databases and schema objects and execute queries. If you just need a Bash for your MySQL container, do a
docker exec -it j-lawyer-mysql-server bash

Note that the –link switch is deprecated and not to be used for production anymore.

Linking application and database containers

As mentioned, linking containers is deprecated. There are other ways of accomplishing the same thing, e.g. creating a wrapper script that starts multiple services or using supervisord. Personally, I prefer having several lightweight containers instead of one larger, so I will continue with using Docker Compose.

Installing Docker Compose

sudo curl -L https://github.com/docker/compose/releases/download/1.21.0/docker-compose-$(uname -s)-$(uname -m)-o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

Then verify the installation by calling

docker-compose --version

Defining your stack

Create a new directory

mkdir j-lawyer-server-stack
cd j-lawyer-server-stack

Create a stack definition

touch j-lawyer-server-stack.yaml

Edit the file and use the following content:

# Use root/example as user/password credentials
version: '3.1'

services:

db:
image: j-lawyer-mysql-server
restart: always
environment:
MYSQL_ROOT_PASSWORD: secret-pwd

server:
image: j-lawyer-server
restart: always
ports:
- 8000:8080

This will define a stack consisting of a MySQL container „db“ based on „j-lawyer-mysql-server“ and a Wildfly container „server“ based on „j-lawyer-server“. Port 8000 will be exposed for the Wildfly containers port 8080.

Launch the stack

sudo docker-compose -f j-lawyer-server-stack.yaml up

If you fire up http://localhost:8000 you will see the Wildfly welcome page. When executing a

sudo docker container ls

you will see both containers defined in your stack, up and running:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1ce321e41104 j-lawyer-server "/usr/local/j-lawyer…" 8 minutes ago Up 8 seconds 0.0.0.0:8000->8080/tcp j-lawyer-server-stack_server_1
676ced50956c j-lawyer-mysql-server "docker-entrypoint.s…" 8 minutes ago Up 9 seconds 3306/tcp j-lawyer-server-stack_db_1

Now, let’s verify the Wildfly container has access to the MySQL container, by starting a Bash inside the Wildfly container in your stack. Note the container name, taken from the output of the last command:

sudo docker exec -it j-lawyer-server-stack_server_1 bash

The host name of the MySQL container matches the MySQL containers logical name in your stack definition (.yaml), in our case „db“. Let’s see if we can ping this:

ping db

You will see this works. Your MySQL container can be reached from within your Wildfly container.

Next Steps

In this tutorial, parts 1 and 2, we have installed Docker, set up a Wildfly image as well as a MySQL image, and defined a stack combining the two. Everything else is pretty straight forward, e.g.

  • Add a datasource configuration for Wildfly in your Wildfly image, pointing to MySQL on the host „db“.
  • Add RUN entries in your MySQL image to create a database and some schema objects
  • Add COPY entries to your Wildfly image to add e.g. a web application archive (.WAR)

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.