Authentication system using Golang and Sveltekit - Dockerization and deployments
Tags: go, docker, devops, javascript
Published: 2023-06-08 19:52:49

## Introduction

Having built out all the features of our application, preparing it for deployment is the next step so that everyone around the world will easily access it. We will deploy our apps (backend and frontend) on free hosting platforms &mdash; [fly.io][1] for backend and [vercel][2].

## Source code

The source code for this series is hosted on GitHub via:

{% github Sirneij/go-auth %}

## Implementation

### Step 1: Dockerization of the backend

Though [fly.io][1] supports Golang natively and we can deploy it just like that, our file structure doesn't make it that easy since `main.go` isn't at the root of the project. To ease the process, we'll just dockerize it. We will adopt [multi-stage builds][3] pattern to greatly reduce our docker image size. With this, we'll have a `Dockerfile` that looks like this:

```docker
<!-- go-auth/Dockerfile -->

FROM golang:1.20-alpine AS builder
WORKDIR /app
COPY ./go-auth-backend/ .
RUN go mod download
RUN go build -ldflags='-s' -o=./bin/api ./cmd/api


FROM alpine:latest AS runner
WORKDIR /
COPY --from=builder /app/bin/api /api
EXPOSE 8080
ENTRYPOINT ["/api"]
```

At the `builder` stage, we are using the compact-sized and secured `alpine`-based docker image. This image is just enough to build our application. Then, we specified `/app` as the directory which our system's source files are copied into. Since we have external dependencies, they need to be downloaded hence the `RUN go mod download`. With everything intact, we then built our application which generated an executable (binary) in `/bin/api`. The binary generated will be reduced in size because we stripped off "[DWARF][4] and [Symbol table][5]".

In the `runner` stage, we simply "brought forward" the output of the `builder` stage &mdash; in this case `/app/bin/api` &mdash; and deposit it in `/api` which was then used as the application's entry point.

It should also be noted that to reduce the image's size further, we ignored some folders and files and they weren't copied to the docker image using a `.dockerignore`:

```docker
# flyctl launch added from frontend/.gitignore
frontend/*
# flyctl launch added from go-auth-backend/.gitignore
go-auth-backend/**/.env.*
go-auth-backend/**/.envrc
go-auth-backend/**/bin
fly.toml
```

### Step 2: Deploying the backend

Before deploying, some changes need to be made to `config.go` and the changes can be seen [here][6].

Before proceeding, kindly create an account on [fly.io][1].

Having wrapped our app in a docker container, it's time to deploy on [fly.io][1]. Ensure you are at the base of the entire project. Then follow the steps below:

- [Install fly.io's CLI][7]
- Login into your account via `fly auth login`
- Run `fly launch`. This automatically detects the `Dockerfile` at the root of the project. Follow the prompts. However, don't deploy it yet because we need to set our environment variables. By now, you should see a `fly.toml` file generated. You should create an `[env]` section in the file with the following filled in:

    ```toml
    [env]
    PORT = "8080"
    DEBUG = "false"
    TOKEN_EXPIRATION = 
    SESSION_EXPIRATION = 
    DB_MAX_OPEN_CONNS = 
    DB_MAX_IDLE_CONNS = 
    DB_MAX_IDLE_TIME = 
    EMAIL_HOST_SERVER = "smtp.gmail.com" # if you are using google's gmail
    EMAIL_SERVER_PORT = "587"
    FRONTEND_URL = 
    ```

    If you have some secrets you can't put here such as `EMAIL_USERNAME`, `EMAIL_PASSWORD`, `AWS_S3_BUCKET_NAME`, `AWS_SECRET_ACCESS_KEY`, `AWS_ACCESS_KEY_ID`, and `AWS_REGION`, they can be loaded using:

    ```shell
    flyctl secrets set SECRET_NAME=value
    ```

    > NOTE: If you opted to create a PostgreSQL database and Redis provided by [fly.io][1], they will automatically be added to your environment variable. Ensure you copy the credentials of the PostgreSQL database provisioned most especially the `DATABASE_URL`. This is needed to migrate the database locally.

    After setting them all, then:
- Run `fly deploy`.
- If successful, run the following command to migrate your database:

    ```shell
    ~/Documents/Projects/web/go-auth/go-auth-backend$ migrate -path=./migrations -database=<DATABASE_URL> up
    ```

### Step 3: Deploying the frontend

Deploying the front-end on [vercel][2] is a breeze. Just install [sveltekit's vercel adapter][8]:

```shell
~/Documents/Projects/web/go-auth/frontend$ npm i -D @sveltejs/adapter-vercel
```

Then add the adapter to your `svelte.config.js`:

```js
// frontend/svelte.config.js
import adapter from '@sveltejs/adapter-vercel';

/** @type {import('@sveltejs/kit').Config} */
const config = {
    kit: {
        adapter: adapter({
            runtime: 'edge'
        })
    }
};

export default config;
```

With that, just go to your Vercel dashboard and link the front-end of your GitHub version of the application to it. Within seconds, your app will be deployed.

Ensure you set the URL of the backend as the `VITE_BASE_API_URI_PROD` environment variable.

Congratulations. The next article will be about automated testing. It's also going to be the last article in this series. See you.

## Outro

Enjoyed this article? I'm a Software Engineer and Technical Writer actively seeking new opportunities, particularly in areas related to web security, finance, health care, and education. If you think my expertise aligns with your team's needs, let's chat! You can find me on LinkedIn: [LinkedIn](https://www.linkedin.com/in/idogun-john-nelson/) and Twitter: [Twitter](https://twitter.com/Sirneij).

If you found this article valuable, consider sharing it with your network to help spread the knowledge!

[1]: https://fly.io/ "Deploy App Servers Close to Your Users"
[2]: https://vercel.com/ "Vercel"
[3]: https://docs.docker.com/language/golang/build-images/#multi-stage-builds "Multi-stage builds"
[4]: https://golang.org/pkg/debug/dwarf/ "DWARF"
[5]: https://medium.com/a-journey-with-go/go-how-to-take-advantage-of-the-symbols-table-360dd52269e5 "Go: How to Take Advantage of the Symbols Table"
[6]: https://github.com/Sirneij/go-auth/commit/aeba6f81be3f3fe98402075f58ab28ee150c376d#diff-cc8eba64200f0f20278f55a1b7781f5c0807bf740aa66eb0797bf12ce61b6678 "go-auth-backend/cmd/api/config.go"
[7]: https://fly.io/docs/hands-on/install-flyctl/ "flyctl"
[8]: https://github.com/sveltejs/kit/tree/master/packages/adapter-vercel "adapter-vercel"