Deploying a Simple web application(Apache2 and Mysql) in Docker and Kubernetes

Image credits:https://arctouch.com/blog/kubernetes-docker-containerized-apps/

Before we proceed : This is not a cyber security related blog , this is just a quick blog of deploying a simple web application with a database attached. It’s actually quite a noobish blog, however I wanted to document the process of deploying the application from scratch (except code which I have stolen from another source). This might become unnecessarily long for some as I’ll be putting in each error I was thrown at and how it was solved, but it’s a necessary lesson to not do anything theoretically and always go ahead and implement something because the struggle will give you some valuable lessons. This blog assumes that you have basic understanding of docker ,containers and kubernetes concepts .

The Service Architecture

It will be a simple web application server where a user will input some data and a mysql database server will store the data. I will be dockerising the application in the url given below.Please download the source code from this blog-post first:

I will be using two containers i.e. an apache2 server for hosting the web application and a mysql container to store user data. I will write a Dockerfile for the apache2 container to run and then run a container for the mysql server and configure the schema accordingly.

Deploying it over Docker

First, I’ll deploy the application using Docker.I am on a ubuntu 20.04 system authenticated in a user in the docker group with docker and minikube installed. The files layout are as shown below:

Configuring the php file to point properly

I will first make a small change before writing our Docker file. Edit the form_submit.php and change the $host variable to whatever you want to name your mysql container (mydb in my case). You can change the root user password if you want to because that’s an environment variable which can be configured accordingly.

Writing the Dockerfile

There a thousand ways of writing a Dockerfile. I have written in my own style, but it can be different as well.

FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install apache2 -y
RUN apt-get install php -y
RUN apt-get install php-mysql -y
ADD . /var/www/html
EXPOSE 80
CMD [“apache2ctl”, “-D”, “FOREGROUND”]

Please note to install php-mysql and php . Without them you cannot run php or connect to mysql database from your apache server. Build the container with this command:

docker build -t “web” .

While building, you might observe this prompt and no matter what you press, you become stuck there:

The container automatically starts configuring tzdata which is user interactive by default. There is a turnaround by addin an env variable line in the Dockerfile like this:

ENV DEBIAN_FRONTEND=noninteractive

Reference:

https://askubuntu.com/questions/909277/avoiding-user-interaction-with-tzdata-when-installing-certbot-in-a-docker-container

Updated Dockerfile:

FROM ubuntu:18.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update
RUN apt-get install apache2 -y
RUN apt-get install php -y
RUN apt-get install php-mysql -y
ADD . /var/www/html
EXPOSE 80
CMD [“apache2ctl”, “-D”, “FOREGROUND”]

Now if you build the docker image, it should be successfully built.

To keep it simple, we are simply installing all our dependencies and copying our code to the proper directory and starting our apache2 server in port 80

Now that our image is built, before running our container, let us first configure our mysql container :

Running the mysql container and pushing our schema

We set up the mysql container as shown below in the image:

We ran the container, used port mapping to map it to localhost(of docker host)and authenticate to the mysql server(password as configured in the form_submit file) and create the table (from the source code page). Command to run the mysql container is below. Please make sure that name is same as one configured in the php file:

docker run — name mydb -p 3306:3306 -e MYSQL_ROOT_PASSWORD=password -d mysql

Running the apache web-server container linking to mysql container

Now we can run the apache web server with this command:

docker run -p 80:80 -P — name web — link mydb:mydb web

We should now see our login page if we navigate to it :

But once we submit data, we get this error:

Upon debugging it, I discovered that the mysql version is not compatible. We need to switch to 5.7 version for it to work with our script.

Reference:

https://matomo.org/faq/troubleshooting/how-to-deal-with-the-error-sqlstatehy0002054-the-server-requested-authentication-method-unknown-to-the-client-when-setting-up-matomo/#:~:text=How%20do%20I%20fix%20%E2%80%9CSQLSTATE,unknown%20to%20the%20client%E2%80%9D%20error%3F&text=When%20setting%20up%20Matomo%2C%20if,are%20using%20MySQL%20version%208.&text=UPDATE%20%60mysql%60.

Changing version of mysql container and deploying the service architecture

Run the mysqlcontainer like this (after removing exisisting container)

docker run — name mydb -p 3306:3306 -e MYSQL_ROOT_PASSWORD=password -d mysql:5.7

Since this is the new container, configure the schema again like before as well.After the containers are deployed, the mysql error should go away once you submit anything in the login form:

And now we should be able to see our data pushed to the database

This means that our app has been deployed successfully and also communicates properly with the backend .

Additionally, I have uploaded the image for the web server in dockerhub, do find it at tripster98/basic-web-app .

Deploying it over Kubernetes

So untill now, I had deployed the application over Docker and linked both the containers. Now I am going to showcase how to deploy it over Kubernetes. Please make sure minikube is installed and up and running before you proceed further.

Let’s start minikube by typing :

minikube start — driver=docker

Before this, I would like to create a mysql docker image with al the required databases and tables specifically for the server which can save some time and make deployment in kubernetes simpler. To do this start a container just like shown initially while configuring the mysql container (Password has to be same), create the database and table as per given application schema, but just before exiting out, run this command to save the dump.

mysqldump -P 3306 — protocol=tcp -u root -p dev_to >dev.sql

Now we’ll write the Dockerfile specifically for our custom mysql container as shown below:

In mysql containers if you want to initialise the database with custome schema, make sure you copy the dump to the /docker-entrupoint-initdb.d directory. This can be a useful tip if you want to create custom initialised mysql images.

You can find the image at tripster98/basic-mysql-db

Kubernetes yaml files

Time to desing the kubernetes yaml files for our task. We will create separate pods for the web server and the mysql server. We shall expose the webserver using nodeport service and expose the database server using clusterIP.

First let’s create the yaml files:

Since it is assumed that the readers have a basic understanding of Kubernetes, the parameters should be easy to follow. Please make sure that the service name for the mysql service is set to mydb because that is the hostname the webapp searches to connect.

Let us start all the pods and services!

As we can see that everything is running successfully. Let’s check the url to access the server and also access the server to see if we have setup everything correctly:

Perfect! As we can see , I have setup a basic full stack web application over Kubernetes .

That’ll be all , thanks folks!

P.S. recently I decided to create a series known as Offensive Security for Containers(OSCON). In this series , I have published vulnerable boot2root images which you would have to exploit and read the flag. If you are someone who want’s to practice cybersecurity skills in a fast and easy way, then please head over to my docker hub page given below.

Cats, pizza and cyber security are all I live for! Follow me for a wide variety of topics in the field of cyber security. OSCP ,CRTE , CRTP ,CKAD holder.