Using docker to build your app.

First steps to build your microservices.

Using docker to build your app.

proyect-id: mn-blg-01-docker-images

Docker is the most popular way to build and architect microservices, and why is it popular now days?

First of all, docker allows you to run any application regardless of the operating system you have, let's say you have a windows server, and you would like to run your Linux based application in your server.

one solution to this problem is to create a virtual machine, install required libraries required for you app and after that mount your application, this is not sounds cool when you have a considerable set of applications.

Instead of this it's more accurate to isolate your application into a lightweight virtual process (container), and this is where docker comes into play, docker will allow you to bypass all of the overhead required to create a VM and the most important thing is, you "build once, run anywhere".


💡
Let's get down to business into an easy-to-understand example:

To begin with, let's take a look into the below service diagram to have a general overview of the problem we want to solve.

Service A.

Our service has three main components, frontend, backend and a database. Now let's define the requirements for each of the components.

componentrequirement
frontendnext.js react web app.
backenddotnet core 8
databasePostgreSQL

for each component we're going to have a Dockerfile, which contains steps to build an image of our application.

as an example, below Dockerfile is part of our backend component, inside a docker image we need to perform three basic steps,

  • copy application files.

  • compile source code.

  • give an entry point, where our application is going to run.

docker process the file as a set of layers, each one composed with the previous one.

put special attention in the FROM sentences:

these sentences help us build our applications with ease, there we're using a predefined image in docker repository, this image is stored in the cloud, and contains required developer tools, or a specific runtime to run an application.

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env
WORKDIR /App

# Copy everything
COPY ./UsersService ./
# Restore as distinct layers
RUN dotnet restore UsersService.csproj
# Build and publish a release
RUN dotnet publish -c Release -o release

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /App
COPY --from=build-env /App/release .
COPY --from=build-env /App/scripts .
#ENTRYPOINT ["dotnet", "UsersService.dll"]
RUN chmod +x start.sh
ENTRYPOINT ["/App/start.sh"]

now, to easy connect each docker container with each other, we're going to make use of docker-compose.

docker compose will help us orchestrate our services, although it is not used for production environments, it's useful when you want to run your services locally, like in this example.

in our file we specify our three main components:

  • database

  • backend

  • frontend

this YML file also contains network information, with each network we're enabling our services to communicate each other.

environment variables will be useful to change our application's settings, and for each service we're giving the context where the Dockerfile is stored.

services:
  backend:
    build: 
     context: ./backend
    environment:
      ConnectionStrings__DefaultConnection: "Host=pg-database;Port=5432;Database=${POSTGRES_DB};Username=${POSTGRES_USER};Password=${POSTGRES_PW}"
    ports:
      - "8000:8080"
    depends_on:
      - pg-database
    networks:
      - backend-network
      - frontend-network

  frontend:
    build: 
     context: ./frontend
    environment:
      NEXT_PUBLIC_SERVICE_URL: "http://backend:8080"
    ports:
      - "5001:3000"
    depends_on:
      - backend
    networks:
      - frontend-network

  pg-database:
    image: postgres
    restart: always
    ports:
      - "8001:5432"
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PW}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_DB: ${POSTGRES_DB}
    networks:
      - backend-network
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

networks:
  backend-network:
   name: backend_network
  frontend-network:
   name: frontend_network

I encourage you to read through the repository code I prepared for this tutorial and try to get more familiar with the concepts.

Docker Images Project

you'll notice how easy is start working with docker images,

before running any docker command, create an .env file on your root project and set these values:

create an .env file inside mn-blg-01-docker-images folder, you can change values for password, username, and database.

POSTGRES_PW="databasepassword"
POSTGRES_USER="databaseuser"
POSTGRES_DB="users"

you only need to run below command, and everything will be prepared to start consuming your service.

docker-compose up -d

after command finishes you will be able access your app through

http://localhost:5001

Did you find this article valuable?

Support Néstor Mejía Pérez by becoming a sponsor. Any amount is appreciated!