Deploying Golang and Angular Applications with Docker and Nginx
Published: 2024-04-23 14:09:31


## Introduction
Welcome to my blog! In this article, I've documented the process of deploying a Golang backend and Angular frontend application using Docker and Nginx. This tutorial will walk you through the steps to set up a production-ready environment for your Golang and Angular applications.

Project Repository
You can find the code for this project on GitHub: [Project Repository](https://github.com/nandes007/image-converter)

My Image Converter Application
Check out the deployed application to see it in action: [My Image Converter](https://my-converter.ninedaystech.com/)

Personal Website
Visit my personal website to learn more about me and my other projects: [ninedaystech.com](https://ninedaystech.com/)

## Choosing your server provider
Before diving into deployment, the first step is to select a reliable server provider. There are several options available, including Google Cloud Platform (GCP), Amazon Web Services (AWS), and others. For this guide, i've chosen DigitalOcean as my server provider for its simplicity, affordability, and robust features. 

To get started with DigitalOcean, you can follow these steps: https://www.digitalocean.com/community/tags/getting-started

## Prepare your project
Let's take an example with a deployment that use docker compose:

Below **Dockerfile** for backend side, like i have mentioned above i develop my simple application using go for the backend
```
# syntax=docker/dockerfile:1

ARG GO_VERSION=1.22

FROM golang:${GO_VERSION}-alpine

ENV GO_ENV production

WORKDIR /usr/src/backend

COPY go.mod go.sum ./

RUN go mod download

COPY . .

RUN CGO_ENABLED=0 GOOS=linux go build -o main ./cmd

EXPOSE 9090

CMD ["./main"]
```

And for the frontend i develop my simple application using **Angular**. Below **Dockerfile** for frontend side:

```
FROM node:20-alpine AS build

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm cache clean --force

RUN npm install -g @angular/cli

RUN npm install
RUN npx ngcc --properties es2023 browser module main --first-only --create-ivy-entry-points

COPY . .

RUN npm run build

FROM nginx:stable

COPY --from=build /usr/src/app/dist/frontend/browser /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
```

In the frontend side, i did [multi-stage](https://docs.docker.com/guides/docker-concepts/building-images/multi-stage-builds) builds in my dockerfile. Because i use [multi-stage](https://docs.docker.com/guides/docker-concepts/building-images/multi-stage-builds/) which is my angular application will run on nginx image, so i need add configuration file for nginx. The configuration file named as _nginx.conf_. Below the example for nginx configuration file:

```
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;

        root   /usr/share/nginx/html;
        index  index.html index.htm;

        location / {
            try_files $uri $uri/ /index.html;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
}
```
And then i will create that image and run the container using docker compose. Below my docker compose configuration:

```
services:
  backend:
    build:
      context: ./backend
    ports:
      - 9090:9090
    volumes:
      - ./backend/converted_images:/go/src/app/converted_images

  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - 8081:80
```
I will run my backend using port 9090 and port 8081 for my frontend. I used port forwarding for my frontend because my nginx run on port 80.

## Deployment section
Okay, let's deploy our project. First you need connect to your server/droplets. Open your terminal and run command like below:

```
ssh username@your_ip_address
```
Then, you need to install docker and nginx in your server. If you using digital ocean maybe this can help you to install docker and nginx: [docker installation guide for ubuntu](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-20-04) and [nginx installation guide for ubuntu](https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-20-04).

### Clone Project
Begin by cloning your project onto your server. I typically place my projects in the `/var/www/html` directory. Once the cloning is complete, navigate to the project directory and run the following command to start your project: `docker compose up -d`

```
CONTAINER ID   IMAGE                      COMMAND                  CREATED        STATUS        PORTS                                       NAMES
c93969a04b43   image-converter-backend    "./main"                 46 hours ago   Up 46 hours   0.0.0.0:9090->9090/tcp, :::9090->9090/tcp   image-converter-backend-1
3856213fb4f5   image-converter-frontend   "/docker-entrypoint.…"   46 hours ago   Up 46 hours   0.0.0.0:8081->80/tcp, :::8081->80/tcp       image-converter-frontend-1
```

### Configure NGINX
After installation done, next we need to tell NGINX to listen to port 80 (http requests) for our custom domain name and map it back to the port we configured in our `docker-compose.yml` file and our app’s production config.

SSH into your server and create a new file in `/etc/nginx/sites-available/` (you can name it yourdomain.com) with the following contents:

```
server {
  listen        80;
  server_name   yourdomain.com www.yourdomain.com;
  location / {
    proxy_pass  http://localhost:9090;
  }
}
```
Next we need to create a symlink to the file for the `/sites-enabled` directory:

```
cd /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/yourdomain.com ./
```
Check that the symlink was created successfully:

```
ls -l

# output:
... yourdomain.com -> /etc/nginx/sites-available/yourdomain.com
```

Next check that the NGINX syntax is OK:

```
sudo nginx -t

# output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
```

Finally restart the service:

```
sudo systemctl restart nginx
```
Note: The above step is only for backend, you can follow the same step and enter the `proxy_pass` with appropriate address

## Conclusion
Congratulations! You've successfully deployed your project to your server. Now, let's access your newly deployed application and ensure that all features are running smoothly. You can find [the project repository](https://github.com/nandes007/image-converter) and [the final result](https://my-converter.ninedaystech.com/).

I hope this guide has been helpful in simplifying the deployment process for you. If you have any questions, feedback, or suggestions for improvement, please don't hesitate to leave a comment below. Your input is valuable and will help us enhance future tutorials.

Thank you for reading, and happy coding!