This is an example of a dockerized golang & svelte application. The result is a tiny scratch
docker image. Both golang app and svelte app are testable during development. Live/Hot reload also work.
NOTE: Any statically compiled UI can be used in place of svelte. Any server that can reverse proxy can be used in place of golang.
The ./app
directory contains the golang server. The ./web
directory contains the nodejs server with svelte. Henceforth, they will be considered app
layer and web
layer.
A single Dockerfile
binds them together.
To run this example, you'll need the following:
Requirements
./dev.sh
is your task runner. As such:
./dev.sh up
./dev.sh stop
./dev.sh down
./dev.sh test
Run a production-like environment with ./dev.sh staging
. Run integration tests or smoke tests on it. Use ./dev.sh port
to discover the port.
For more commands: ./dev.sh
The core of the structure is the root files. They control how the whole application is assembled.
TLDR; To make it your own: copy root files over and create golang in ./app
and nodejs in ./web
. The ./app
will need to serve ./static
for production, and reverse proxy web:3000
for development.
Here are the steps to reproduce the structure for your own project, as well as some areas to edit:
dev.sh
. Change PORT, add extra helper commands (like db
), add loading test fixtures in init
section. This is application task runner.docker-compose.yml
related files, rename images, add environment variables and other services (like db
).Dockerfile
and rename output binary../app
directory and copy app/air.toml
. Rename output binary here too.go mod init <name>
in the ./app
directory../app/.gitignore
file with tmp/
and output binary name.npm init vite@latest
, name it web
, select svelte
../dev.sh init
to run in development mode.As you work on each layer, the live-reload or hot-reload will recompile for you. You can manually rebuild with ./dev.sh up --build
. Test with ./dev.sh test
.
When your app is ready to deploy, build the final docker image: IMAGE=username/project:1.0.0 ./dev.sh build
.
There's two modes: development and production modes.
Production mode is what you use to deploy a production-ready app. Build with IMAGE=username/project:1.0.0 ./dev.sh build
.
The golang app will to serve the /static
directory when it detects this mode.
A scratch
image is built to run the complete app within a single service. It's built with multi-stage builders, nodebuilder
and gobuilder
. The nodebuilder
builds static files. The gobuilder
builds the app binary. They are combined into a scratch
image with /app
as the binary while /static
contains the static files.
In development mode, two services start; one web
running nodejs
image and the other app
running golang
image.
The golang app serve its API endpoints and reverse proxy to the web
layer when it detects development mode.
Each layer is independent and testable: ./dev.sh test
to test both layers.
Code changes trigger live-reload thanks to air.
./dev.sh test-app
./dev.sh logs
Code changes will trigger hot-reload thanks to vite.
./dev.sh test-web
./dev.sh logs web