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 testRun 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 logsCode changes will trigger hot-reload thanks to vite.
./dev.sh test-web./dev.sh logs web