Skip to content

Commit

Permalink
rewrite the blog
Browse files Browse the repository at this point in the history
  • Loading branch information
SagarGi committed Nov 26, 2023
1 parent 1392baa commit 2db92d1
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 90 deletions.
276 changes: 186 additions & 90 deletions src/assets/DockerCompose/docker_compose.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,112 +4,208 @@ authorName: Sagar Gurung
authorAvatar: https://avatars.githubusercontent.com/u/46086950?v=4
authorLink: https://github.com/SagarGi
createdAt: Aug 31, 2023
tags: docker-compose, docker, containerization, yaml
banner: https://raw.githubusercontent.com/DevExpress/testcafe-gh-page-assets/master/src/images/testcafe-ogp-icon.png
tags: docker-compose, docker, containerization, yaml, services
banner: https://blog.jankaritech.com/src/assets/DockerCompose/images/docker-cmopose-background.png
---

In this blog we will basically be containerizing a web application consisting of `MySQL`, `phpmyadmin`, `frontend` and `backend` as service using docker compose.
Also, briefly get into how all those services are running and how multiple services make up an application running in multiple containers
> Note: This article does not provide concepts of docker. To know concepts of docker [visit here.](https://blog.jankaritech.com/#/blog/How%20to%20use%20selenium%20in%20docker%3F)
Setting up an application can be a bit hefty if application is dependent to various services when setting up locally. But we can easily configure and containerize the whole application and its services in a single docker compose file and make the whole application running not only in your machine but in whole development environment.
In this blog we will make a basic `docker-compose.yml` for a simple demo web application to make it run through the `yaml` file in your machine. So lets get right into it.
## Brief About Docker Compose
In very short a docker compose helps to define and run docker applications in multiple containers. With docker compose we can define a `yml` file where we can define our services, networks, volumes required for our application to get it running. Basically configuring, defining and managing all the necessary things required for our application becomes easy with docker cmopose.

And in this blog we will also be defining and configuring simple services for our application through a compose file and run it using docker compse.

## What is the application about (to be run with docker compose)?
The application we will be running with docker compose has mainly 3 services:
1. `frontend` service
2. `backend` service
3. `mysql service` (database service)

Also, we will be running the 4th service `phpmyadmin` which is used for managing and administering the MySQL through GUI.
This is a very simple application for demo, where in `mysql` database there are lists of user information and through the `frontend` service we will request to `backend` service to get all those users and to be listed in our application UI. Like this all those application services are dependent and collaborating to each other. We will be configuring the exact same thing through docker compose.

## Prerequisites
For better understanding how we write a docker compose yaml file, it is better to understand how you set up the application locally in your machine. I urge to set the demo web application into your system. For that the following things needs to be installed.
- [Node.js](https://nodejs.org/en) version 16 or above. (needed for local setup - optional)
- MYSQL (needed for local setup - optional)
- [Docker](https://docs.docker.com/engine/install/)
- And [docker compose](https://docs.docker.com/compose/install/)
Before we start, lets make sure following things get installed into your system.
1. install [docker](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-20-04)
2. install [docker compose](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-20-04)
> Note: I will be doing the whole setup with Ubuntu 22.04 LTS. Things might differ if you have different operating system.
> Note: For this blog the whole setup is done in ubuntu 22.04 LTS
## Getting Started

## Setting up wep application locally (Optional)
I assume all the requirements above is installed in your machine. So, lets set up the demo web application locally.
I have a web application which has frontend `demo-web` and backend `demo-server` in `github` publicly available. It is a very basic web application built in `vue-js` that uses `mysql` as database. With this basic application we can register the user and view the registered user in the web.
Let's get right into setting it up.
1. To set up `front-end`, visit [demo-web](https://github.com/SagarGi/demo-web) and follow the `read-me` section to set up manually in your machine.
2. To set up `back-end`, visit [demo-server](https://github.com/SagarGi/demo-server) and follow the `read-me` section to set up manually in your machine.
Since we have enough information about the application And, also I assumed that the prerequisites are fulfilled. we can now jump to the section for defining and configuring our application with docker compose.

> Note: Please follow the `read-me` set the application locally since it will be easier to write docker compose yaml file.
### Initiate file structure
1. create a directory `dockercompose`
2. create a docker compose yml file `dockercompose/compose.yml` inside it.
3. Also create an empty `testdump.sql` file (will mention the use of it later)

If you were able to set up the whole application locally then kudos, it will make very easy to write docker compose file. Now, we will be creating a docker compose file through which we will be setting up and running the whole application.
It should look something like this.
```
📦dockercompose
┗ 📜compose.yml
┗ 📜testdump.sql
```

### Defining and configuring services

Now inside the `compose.yml` lets define and configure the services for our application.

1. database service (mysql)

```yml
version: "3.8"

services:
database:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: demodb
volumes:
- ./testdump.sql:/docker-entrypoint-initdb.d/testdump.sql
restart: always
```
Here, defining services in docker compose we use keyword `services`. We have defined our service `database` configured with `image:mysql` and `environment` variables required for it.
We can see it has a volumes keyword used here. Simply through volume we can mount our local data to the docker container. In this context we have mapped `testdump.sql` which is in our
local root directory and ran as an entrypoint when the container starts. It means when `database` service is started in a container the `testdump.sql` is the first thing which run inside the container.
And entrypoint script basically creates 4 users in the database. So we need to add some sql command inside of `testdump.sql` as:
Like this we defined and configured database service for our application.

```sql
CREATE TABLE users(userid INT PRIMARY KEY AUTO_INCREMENT, fullname VARCHAR(60), email VARCHAR(60));
INSERT INTO users (fullname, email) VALUES ('Alice Smith', 'alice@example.com');
INSERT INTO users (fullname, email) VALUES ('Bob Johnson', 'bob@example.com');
INSERT INTO users (fullname, email) VALUES ('Eva White', 'eva@example.com');
INSERT INTO users (fullname, email) VALUES ('Michael Brown', 'michael@example.com');
ALTER USER 'root' IDENTIFIED WITH mysql_native_password BY 'root';
flush privileges;
```
2. backend service

```yml
backend:
image: sagar4321/demo-server
environment:
PORT: 3001
DBHOST: database
DBPORT: 3306
DBUSER: root
DBNAME: demodb
DBPASSWORD: root
restart: always
ports:
- "3001:3001"
depends_on:
- database
```

Similarly, we define and configure our backend as above with necessary `image:sagar4321/demo-server` (this image is built and pushed to docker hub which I created), `environment` and `port 3001` (port where the server listen)
Here, we have another keyword `depends_on` which has value `database` service, that means that `backend` service is only ran after `database` successfully run.

3. frontend service

```yml
frontend:
image: sagar4321/demo-web
environment:
SERVER_URL: http://0.0.0.0:3001
ports:
- 8080:8080
depends_on:
- backend
```

Same definition and configuration for the `frontend` service with `image: sagar4321/demo-web` (which I built and pushed to docker hub), `environment` and `port 8080` (where the `frontend` service listen).
But here the `frontend` service depends on `backend` service since it needs to be started before the `frontend` service.

4. phpmyadmin service

```yml
phpmyadmin:
image: phpmyadmin/phpmyadmin
restart: always
environment:
PMA_HOST: database
PMA_PORT: 3306
ports:
- "8081:80"
depends_on:
- database
```
Also, same thing applies defining and configuring `phpmyadmin` services. It also depends on `database` services. And listen to `port:8081`

Now the overall `compose.yml` file after combining all the services together looks something like this as one:

```yml
version: "3.8"
services:
database:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: demodb
volumes:
- ./testdump.sql:/docker-entrypoint-initdb.d/testdump.sql
restart: always
server:
image: sagar4321/demo-server
environment:
PORT: 3001
DBHOST: database
DBPORT: 3306
DBUSER: root
DBNAME: demodb
DBPASSWORD: root
restart: always
ports:
- "3001:3001"
depends_on:
- database
web:
image: sagar4321/demo-web
environment:
SERVER_URL: http://0.0.0.0:3001
ports:
- 8080:8080
depends_on:
- server
phpmyadmin:
depends_on:
- database
image: phpmyadmin/phpmyadmin
restart: always
environment:
PMA_HOST: database
PMA_PORT: 3306
ports:
- "8081:80"
## Building image locally
While writing compose file we will be using the docker image of our `front-end` and `back-end` and also `mysql` so that all of them can run in the container so that with the help of `docker compose` tool those services running in different container can be start and managed as a single unit.
For that lets create docker image for `front-end` and `mysql`. But for `mysql` we will be building it while running the container itself.
### Create docker images
1. Inside the root directory of the `demo-web` run the following command
```bash
docker build -t font-end .
```
2. Inside the root directory of the `demo-server` run the following command
```bash
docker build -t back-end .
```
3. Check if the built images are locally available with the following command
```bash
docker images
```
The output should be as:

Yes, we have finally completed setting up our required services for our application through the compose file `compose.yml`
Now all it takes is the below single command to run the whole services in multiple containers and get up our application running.
From the directory `dockercompose` in the terminal just run the command as:
```console
REPOSITORY TAG IMAGE ID CREATED SIZE
back-end latest 993a0f768a01 13 seconds ago 1.11GB
font-end latest 2f97413050fe About a minute ago 1.22GB
docker-compose -f compose.yml up
```

Now that we have the docker images of `fron-end` and `back-end` locally we are set to create a compose file.
The command get up all the services running together, just wait a while so that all those services get up running, then we can
see our application running in the browser. You can see different logs of provided by different services in the console

## Creating docker compose file and running web application-
- Inside the root directory of the `demo-server` create a file name as `docker-compose.yml`
- Inside the created `docker-compose.yml` file lets define our required services i.e `front-end`, `back-end` and `mysql`
1. Defining `mysql` service
```yaml
version: "3.8"
After a while we can access our `frontend` in our localhost which is running in port `8080`. Accessing the `frontend` services shows the list of users
that we created in the database. Simply the `frontend` service makes request to `backend` service, while `backend` service gets data from the `database` and
the data is returned to the `frontend` service which is rendered in the User Interface. This is how multiple services running in different container can collaborate
to each other through configuration using docker compose. There are lots of thing we can do through docker compose but this is just the basic of it.

services:
db:
build: ./Database
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=pass
- MYSQL_DATABASE=demodb
restart: always
```
Here we have defined `db` service which is `mysql` required for our web application as database. In the above service `db` is the name of service, the build configuration option builds the image of mysql inside of directory `./Database` which basically consists of docker file and other configuration to set up the mysql running inside of a container.
2. Defining `fontend` service
```yaml
frontend:
image: front-end #the image we built locally
ports:
- "8080:8080"
environment:
- SERVER_URL=http://0.0.0.0:3001
depends_on:
- backend
```
3. Defining `backend` service
```yaml
backend:
image: back-end #the image we built locally
ports:
- "8080:8080"
environment:
- PORT=3001
- DBHOST=db
- DBPORT=3306
- DBUSER=root
- DBNAME=demodb
- DBPASSWORD=pass
depends_on:
- db
```
Here in step `b and c` we have defined both `frontend` and `backend` services with different `environment` required to run it. The services use the local `image` that was built earlier `front-end` and `backend`. Also, both have `ports` option to be accessed to your host from the container.
Also `depends` option is used in both, for `frontend` service to run `backend` needs to run before it and also same applies for `backend` service which depends on `mysql` service.
<br></br>
Now the complete `docker-compose.yml` looks something like this.
```yaml
```
The application page you should get should be something like this in the browser https://localhost:8000:

![Application In Browser](/src/assets/DockerCompose/images/front-end.png)

And that all, I hope this blog was a bit useful for you on how we can run multiple services in multiple docker containers of an application as one using the docker compose.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/DockerCompose/images/front-end.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2db92d1

Please sign in to comment.