Ruddra.com

Ship Application with Database Inside Docker Container

Ship Application with Database Inside Docker Container

DISCLAIMER: This is not the recommended process. Ideally you should have the database running in a separate container and use network to interact with that container.

Usually, we don’t ship application with the database inside the same container. But sometimes we are forced to do that. In this article we are going to see a minimalist way of shipping application with database built-in inside docker container.

Overview of the implementation

We will inherit the database image(ie official PostgreSQL image or MySQL image etc) as base and build it from there. We will write our own entrypoint script, and call the parent image’s entrypoint script** inside our entrypoint** with arguments we receive from CMD directive. With that, we will run additional commands which are required for running our application. Key points to remember here are:

  1. Override the base image’s entrypoint script inside our entrypoint script.
  2. Keep the CMD of the child(our Dockerfile) same as the parent. For example: CMD ["postgres"] for PostgreSQL, CMD ["mysqld"] for MySQL.
  3. In our entrypoint, we will add additional commands and scripts for running our application.

Codes for PostgreSQL based image

Write Dockerfile for PostgreSQL

First let us write a Dockerfile based on postgres:12-alpine:

FROM postgres:12-alpine
ENV POSTGRES_USERNAME 'postgres'
ENV POSTGRES_PASSWORD 'postgres'
ENV POSTGRES_DB 'postgres'

# Install your dependencies here
WORKDIR /src
ADD ./src /src
COPY my-entry-point.sh /
RUN chmod +x /my-entry-point.sh
# not necessary if you are planning to run commands without a bash file
COPY application-related-commands.sh /
RUN chmod +x /application-related-commands.sh
# entrypoint
ENTRYPOINT ["/my-entry-point.sh"]
CMD ["postgres"]
# expose port necessary for your application
EXPOSE 8000

Now, write necessary commands inside application-related-commands.sh to run our app and put it in the same directory as Dockerfile. Finally add your my-entry-point.sh in the same directory as Dockerfile like this:

#!/bin/sh
/usr/local/bin/docker-entrypoint.sh "$@" & /application-related-commands.sh

Instead of /application-related-commands, you can add your custom commands without needing any files.

Here we are running the parent image’s(PostgreSQL) entry point script by /usr/local/bin/docker-entrypoint.sh because if you check the source code in github, you will see that the entry point script is being stored in /usr/local/bin/ folder.

Build and run docker with PostgreSQL

Use this command to build:

docker build . -t psql-based-image

And run with:

docker run -p 8000:8000 -v /your/path:/var/lib/postgresql/data/ -t psql-based-image

Codes for MySQL based image

Write Dockerfile for MySQL

This is similar to the above implementation, apart from the CMD directive. Let us write a Dockerfile based on mysql:8:

FROM mysql:8
ENV MYSQL_ROOT_PASSWORD 'mypassword'

# Install your dependencies here
WORKDIR /src
ADD ./*.jar /src/runable.jar
COPY my-entry-point.sh /
RUN chmod +x /my-entry-point.sh
# not necessary if you are planning to run commands without a bash file
COPY application-related-commands.sh /
RUN chmod +x /application-related-commands.sh
# entrypoint
ENTRYPOINT ["/my-entry-point.sh"]
CMD ["mysqld"]
# expose port necessary for your application
EXPOSE 7654

Implementation of the rest of the stuff(my-entry-point.sh and application-related-commands.sh) are same as PostgreSQL image based implementation.

Build and run docker with MySQL

Use this command to build:

docker build . -t mysql-based-image

And run with:

docker run -p 7654:7654 -t mysql-based-image

Working examples in github

In this article, we have seen an overview on how we might be able to ship applications with database. For working examples, please checkout this repository on github. It has examples of:

In conclusion

I still think this solution is far from perfect, maybe you can suggest better ideas. Let us discuss more in the comment section below.

Last updated: Apr 05, 2024


← Previous
Maintain Authentication Layer from Redux Middleware Using React Router

Maintaining authentication layer in ReactJS can be painful. Back in the old days(even now-a-days), …

Next →
Hugo: Deploy Static Site using GitHub Actions

If you are using Hugo to generate static pages, you are familiar with CLI commands which are to …

Share Your Thoughts
M↓ Markdown