Installation

I. Docker setup #

Make sure you have Docker installed on your machine. You can use Docker Desktop for all three environments: Mac, Linux and Windows. You can refer to the suggestions below.

For the Windows environment, use WSL2 (Windows Subsystem for Linux) and install Ubuntu App from Microsoft Store. You will have completely Linux env

On the Linux environment (Ubuntu). If you are too familiar with Docker. Then there is no need to install Docker Desktop. Using the command line also helps save resources on the computer.

TIP on Mac
On the Mac environment, you should use OrbStack instead of Docker Desktop because it has certain benefits. Can help you run faster and more conveniently when using DNS for each docker instance.

Makefile #

We created a Makefile and checked it work on Mac, Linux (Ubuntu), Windows (WSL2) operator systems.

DOCKER_PATH= /home/gfly/app
MIGRATION_FOLDER = $(DOCKER_PATH)/database/migrations/mysql
DATABASE_URL = mysql://user:secret@tcp(db:3306)/gfly

docker.image:
	docker-compose -f docker/docker-compose.yml build --no-cache --build-arg hostUID=1000 --build-arg hostGID=1000 web

docker.start: docker.run docker.logs
docker.checking: docker.critic docker.security docker.lint

docker.migrate.up:
	docker exec -it --user gfly gfly-web migrate -path $(MIGRATION_FOLDER) -database "$(DATABASE_URL)" up

docker.migrate.down:
	docker exec -it --user gfly gfly-web migrate -path $(MIGRATION_FOLDER) -database "$(DATABASE_URL)" down 1

docker.critic:
	docker exec -it --user gfly gfly-web gocritic check -enableAll -disable=unnamedResult,unlabelStmt,hugeParam,singleCaseSwitch ./...

docker.vulncheck:
	docker exec -it --user gfly gfly-web govulncheck ./...

docker.security:
	docker exec -it --user gfly gfly-web gosec ./...

docker.lint:
	docker exec -it --user gfly gfly-web golangci-lint run ./...

docker.test:
	docker exec -it --user gfly gfly-web go test -v -timeout 30s -coverprofile=cover.out -cover ./...
	docker exec -it --user gfly gfly-web go tool cover -func=cover.out

docker.swag:
	docker exec -it --user gfly gfly-web swag init
	docker exec -it --user gfly gfly-web cp $(DOCKER_PATH)/docs/swagger.json $(DOCKER_PATH)/public/docs

docker.run:
	docker-compose -f docker/docker-compose.yml -p gfly up -d web

docker.logs:
	docker-compose -f docker/docker-compose.yml -p gfly logs -f web

docker.shell:
	docker-compose -f docker/docker-compose.yml -p gfly exec --user gfly web bash

docker.root:
	docker-compose -f docker/docker-compose.yml -p gfly exec web bash

docker.stop:
	docker-compose -f docker/docker-compose.yml -p gfly kill

docker.delete:
	docker-compose -f docker/docker-compose.yml -p gfly down

docker.destroy: docker.stop docker.delete

docker.build: docker.checking docker.vulncheck docker.test docker.shell

docker.release: docker.checking docker.test docker.shell

Build image #

Run below command to create docker image gfly-web

make docker.image

Note: The docker image gfly-web comes with Go, and development tools gocritic, gosec, golangci-lint, swag, migrate, air

Start app #

make docker.start

Command docker.start will run both commands docker.run to run all docker instances in the app. And also run docker.logs to help you have a quick view of running status.

Check docker instances were created.

docker ps                                                                                                                                                                                                                                       ─╯

CONTAINER ID   IMAGE                    COMMAND                  CREATED        STATUS                   PORTS                                                        NAMES
49c6d11d5742   gfly-web                 "/init"                  21 hours ago   Up 5 seconds             80/tcp, 443/tcp, 0.0.0.0:7789->7789/tcp, :::7789->7789/tcp   gfly-web
950451f2fe97   mailhog/mailhog          "MailHog"                21 hours ago   Up 9 seconds             1025/tcp, 0.0.0.0:8025->8025/tcp, :::8025->8025/tcp          gfly-mail
b1078e2cad59   redis:6.2.5-alpine3.14   "docker-entrypoint.s…"   21 hours ago   Up 9 seconds             6379/tcp                                                     gfly-redis
5c5c2619bece   mysql:8.0.25             "docker-entrypoint.s…"   21 hours ago   Up 9 seconds (healthy)   33060/tcp, 0.0.0.0:33060->3306/tcp, :::33060->3306/tcp       gfly-db

Note: A new network name gfly_default was created.

Check app #

Open browser URL http://localhost:7789/

Or http://web.gfly.orb.local/ if you run Docker with OrbStack

Check tools #

For the first time start docker instance. You should run docker.checking, docker.test and docker.swag to make sure everything about docker works correctly.

make docker.checking
make docker.test
make docker.swag

Shell access #

gFly’s docker image provides 2 shell access.

One account is gfly. Use for almost all actions

make docker.shell

and root user

make docker.root

Stop app #

Stop all docker instance of gFly app

make docker.stop

Delete app #

If you have any change in docker files. So, you should delete everything in Docker before rebuild.

make docker.delete

Note: You can use below command to stop and delete app

make docker.destroy

II. Local setup #

Below install steps work with Mac, Linux. For Windows, you should perform all below steps in Ubuntu App (Use WSL2).

TIP
We recommend using Homebrew to install development tools.

Setup Development Tools #

Install development tools gocritic, gosec, golangci-lint, govulncheck, swag, migrate, air into your local machine.

Install gocritic #

brew install go-critic

Refer https://formulae.brew.sh/formula/go-critic

Or

go install github.com/go-critic/go-critic/cmd/gocritic@latest

Checking

gocritic version

gocritic version: v0.10.0

Install gosec #

brew install gosec

Refer https://formulae.brew.sh/formula/gosec

Or

go install github.com/securego/gosec/v2/cmd/gosec@latest

Checking

gosec -version

Summary:
  Gosec  : 2.18.2
  Files  : 0
  Lines  : 0
  Nosec  : 0
  Issues : 0

Install golangci-lint #

brew install golangci-lint

Refer https://formulae.brew.sh/formula/golangci-lint

Checking

golangci-lint version

golangci-lint has version 1.55.2 built with go1.21.3 from e3c2265f on 2023-11-03T12:59:25Z

Install govulncheck #

brew install govulncheck

Or
go install golang.org/x/vuln/cmd/govulncheck@latest

Refer https://formulae.brew.sh/formula/govulncheck

Checking

govulncheck -version
...
Scanner: govulncheck@v1.0.1

Install swag #

go install github.com/swaggo/swag/cmd/swag@latest

Refer https://github.com/swaggo/swag

Checking

swag --version

swag version v1.16.2

Install migrate #

brew install golang-migrate

Refer https://formulae.brew.sh/formula/golang-migrate

Checking

migrate --version

4.16.2

Install air #

go install github.com/cosmtrek/air@latest

Refer https://github.com/cosmtrek/air

Checking

air -v

  __    _   ___
 / /\  | | | |_)
/_/--\ |_| |_| \_ v1.49.0, built with Go go1.21.4

Makefile #

APP_NAME = app
CLI_NAME = artisan
BUILD_DIR = $(PWD)/build
MIGRATION_FOLDER = $(PWD)/database/migrations/postgresql
DATABASE_URL = postgres:/user:secret@localhost:5432/gfly?sslmode=disable

all: critic security lint test swag build

critic:
	gocritic check -enableAll -disable=unnamedResult,unlabelStmt,hugeParam,singleCaseSwitch ./...

security:
	gosec ./...

lint:
	golangci-lint run ./...

test:
	go test -v -timeout 30s -coverprofile=cover.out -cover ./...
	go tool cover -func=cover.out

test.cover:
	go tool cover -html=cover.out

build: critic security lint test
	CGO_ENABLED=0 go build -ldflags="-w -s" -o $(BUILD_DIR)/$(APP_NAME) main.go
	CGO_ENABLED=0 go build -ldflags="-w -s" -o $(BUILD_DIR)/$(CLI_NAME) app/console/cli.go

run: swag build
	$(BUILD_DIR)/$(APP_NAME)

start: run

migrate.up:
	migrate -path $(MIGRATION_FOLDER) -database "$(DATABASE_URL)" up

migrate.down:
	migrate -path $(MIGRATION_FOLDER) -database "$(DATABASE_URL)" down

air:
	air main.go

swag:
	swag init
	cp ./docs/swagger.json ./public/docs

release:
	mkdir -p bin
	# 64 bit - Windows
	GOOS=windows GOARCH=amd64 go build -o $(BUILD_DIR)/$(APP_NAME)-amd64.exe *.go
	# 64-bit - Mac
	GOOS=darwin GOARCH=amd64 go build -o $(BUILD_DIR)/$(APP_NAME)-amd64-darwin *.go
	# 64-bit - Mac ARM
	GOOS=darwin GOARCH=arm64 go build -o $(BUILD_DIR)/$(APP_NAME)-arm64-darwin *.go
	# 64-bit - Linux
	GOOS=linux GOARCH=amd64 go build -o $(BUILD_DIR)/$(APP_NAME)-amd64-linux *.go
	# 64-bit - Linux ARM
	GOOS=linux GOARCH=arm64 go build -o $(BUILD_DIR)/$(APP_NAME)-arm64-linux *.go

Install Redis #

Install

brew install redis

Refer https://formulae.brew.sh/formula/redis Start

brew services start redis

Install Database #

Install MySQL #

brew install mysql

Refer https://formulae.brew.sh/formula/mysql Start

brew services start mysql

Install PostgreSQL #

brew install postgresql@14

Refer https://formulae.brew.sh/formula/postgresql@14

Start

brew services start postgresql@14

Login on Mac

psql -U <USER_NAME> -d postgres

Note: <USER_NAME> is Mac user.

Login on Linux (Windows with WSL2)

psql -d postgres

Create database

postgres:# CREATE DATABASE gfly;

Create user

psql -h localhost -U <USER_NAME> -d gfly
or
postgres:# \c gfly;

gfly-# CREATE ROLE "user" WITH LOGIN PASSWORD 'secret';
gfly-# ALTER ROLE "user" CREATEDB;
gfly-# GRANT ALL PRIVILEGES ON DATABASE gfly TO "user";
gfly-# GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA "public" TO "user";
gfly-# GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA "public" TO "user";
gfly-# GRANT ALL ON SCHEMA public TO "user";
gfly-# \q

Login gfly DB

psql -h localhost -U user -d gfly

Install Mail #

Install

brew install mailhog

Start

brew services start mailhog

Check http://localhost:8025

Refer https://formulae.brew.sh/formula/mailhog

Configuration #

Copy .env file from .env.example

cp .env.example .env

Update .env file

DB_DRIVER="postgresql"
...
DB_USERNAME="user"
DB_PASSWORD="secret"
...
MAIL_HOST=localhost
MAIL_PORT=1025
...
SESSION_TYPE="redis"

Update Makefile file

MIGRATION_FOLDER = $(PWD)/database/migrations/postgresql
DATABASE_URL = postgres://user:secret@localhost:5432/gfly?sslmode=disable

Run App #

Checking #

Run below commands to make sure all above steps work correctly.

make critic
make security
make lint
make test
make swag
make build

Start app #

make start

DB migration #

Migrate DB

make migrate.up

Rollback DB

make migrate.down

Live Mode #

During the development phase, you don’t need to rebuild every time there is a code change

make air