Basic setup for projects with Golang
Tags: go, beginners
Published: 2024-05-14 02:08:14

[Post original in my blog](https://wordpress.com/post/edulixir.com/132).

[PART 2](https://dev.to/ronnymedina/golang-logging-configuration-with-zap-practical-implementation-tips-6g7)

Hi everybody! In this post, I'm going to explain how to create a Golang project with Docker. [Video en español en mi canal](https://www.youtube.com/@codelixir1123).

[This repository contains the code](https://github.com/ronnymedina/tutoriales/tree/main/basic-setup-golang).

### Requirements

- Docker installed
- Basic knowledge with docker
- Docker compose installed

### Structure project

The structure for this project is very simple. 

- **app**: Contains all the files of our application.

- **main.go**: Application entry point.

- **Dockerfile**: Dockerfile to build our image.

- **docker-compose.yml**: File to help build our image more easily.

- **go.mod**: File to track your project dependencies.
```
your-folder-project
    app
       main.go
       run.sh
       go.mod
    Dockerfile
    docker-compose.yml
```
### Dockerfile

```Dockerfile
FROM golang:1.22.3-bullseye

ENV APP_ENV prod
ENV WORDIR_APP /usr/src
ENV BINARY_NAME main
ENV BINARY_PATH ${WORDIR_APP}/${BINARY_NAME}

WORKDIR ${WORDIR_APP}
COPY app/go.mod app/run.sh ./

RUN go mod download && \
    go mod verify && \
    go install github.com/cosmtrek/air@v1.51.0

WORKDIR ${WORDIR_APP}/app

COPY ./app .

RUN go build -v -o ${BINARY_PATH}

CMD [ "bash", "run.sh" ]
```

In this file we define image version FROM `golang:1.22.3-bullseye`. Then there are 4 environments.

- **APP_ENV**: This environment is used to manage the mode in which our application is running. We use values like: (`prod`, `develop`, `test`).

- **WORDIR_APP**: It is the location when we are working.

- **BINARY_NAME**: This is the name of our application when it is finally built. You can use any name that you want. 

- **BINARY_PATH**: This is the full path of our binary when the application is built.

On line **11**, we're installing all dependencies in our project, and additionally, we add this library to enable [live-reload](https://github.com/cosmtrek/air?tab=readme-ov-file#overwrite-specify-configuration-from-arguments) functionality in our application.

I think that was the most important thing in **Dockerfile**.

### go.mod

This file is to track dependencies in your project. You can check the basic tutorial.
```
module example/demogo

go 1.22.3
```

module: The name of your package.

go: Golang version. In this case this version must be the same one that we use in our Dockerfile

### run.sh
```bash
#!/bin/bash

echo "=== Start app in (${APP_ENV}) ==="

env=${APP_ENV:-}

if [ "$env" = "prod" ]; then
    # exucute binary
    ${BINARY_PATH} 
else
    air --build.cmd "go build -v -o ${BINARY_PATH}" --build.bin "${BINARY_PATH}"
fi
```

In this file, we have a conditional to execute a command depending on whether **APP_ENV** is **prod** or **develop**. If **APP_ENV** is **prod**, it executes the binary that we previously compiled in our **Dockerfile**. Otherwise, we execute the air command to use live reload in our app.

### docker-compose.yml
```yml
version: '3'
services:
  demogolang:
    build: .
    environment:
      - APP_ENV=develop
    volumes:
      - ./app:/usr/src/app
```
### Start app

To start our application we only have to execute the following command: `docker compose up`.


### RELATED

- [https://dev.to/ronnymedina/query-large-amounts-of-data-from-bigquery-faster-with-golang-4j61](https://dev.to/ronnymedina/query-large-amounts-of-data-from-bigquery-faster-with-golang-4j61)