Why?
In my Go Project series, I recommended using Makefiles for executing
project-related tasks and Docker for constructing and exporting images. Lately,
I've been replacing these two tools with just instead of make and podman,
instead of docker.
The main advantage podman has over Docker in the case where you are only generating
images for export is that it does not require an external daemon to run. Additionally,
the need for a .hcl is eliminated.
Since most of the cases I've used for make are just commands or tasks that
need to run to build and perform operations on the project, and since we are
not actually checking dependencies to determine what needs to be built, just,
works as well, if not better. Bonus, using just eliminates the need for all
of the .PHONY directives in the file.
Installing just.
Visit Just's Github Repository for
instructions specific to your operating system. However, if you have rust and
cargo installed, you should be able to install it using:
cargo install just
Installing podman.
Usually, podman is provided using your operating system's package manager. For
Debian-based systems, you can use:
apt install podman
Setting up subuid and subgid for podman
Podman has the capability of running containers in rootless mode - it handles
this by using system uids and gids that are lower than the current user's.
Although we are just using Podman to generate containers and not necessarily to run them, you may run into issues when building images. To fix this, you can run the following command to add subuids and subgids to your user (replace
<username> with your actual user:
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 <username>
If you have multiple users on the same system, you may need to run this command
for them as well - be sure to use different ranges such as 200000-265535.
After adding the necessary subuids and subgids, it is necessary to migrate
podman:
podman system migrate
The Justfile
I've created a branch in the Go Getting Started repository with the changes
required to migrate from make and docker to just and podman. I will
outline all the changes here.
Copy or rename the Makefile:
mv Makefile Justfile
Remove any .PHONY directives since they are no longer needed.
The TAG variable assignment needs to be changed. You can use backticks to run commands and assign them to a variable, also, we can use interpolation instead of exporting it to the environment, so we can remove the export:
TAG := `git describe --tags --always`
Since we are using variable interpolation, we can make things easier on ourselves by setting additional variables:
APP_NAME := "go-getting-started"
IMAGE_NAME := APP_NAME + ":" + TAG
TAR_NAME := APP_NAME + "-" + TAG + ".tar"
Our build step remains unchanged. For the docker-build we can simplify this
using our variable - note that anything within double braces {{}} will be
replaced in the command:
docker-build: build
podman build -t {{IMAGE_NAME}} .
Now to export the image as a tar file, we can update the image step - note, we add the additional step of removing the tar file if it already exists:
image: docker-build
mkdir -p image/
if [ -f image/{{TAR_NAME}} ]; then rm image/{{TAR_NAME}}; fi
podman save -o image/{{TAR_NAME}} {{IMAGE_NAME}}
Since just is a command runner, we can also add additional helper steps such
as run - which will build and run our project:
run: build
./build/app
For full reference, here is our full Justfile:
# Justfile for building the Go application and creating a Docker image.
TAG := `git describe --tags --always`
APP_NAME := "go-getting-started"
IMAGE_NAME := APP_NAME + ":" + TAG
TAR_NAME := APP_NAME + "-" + TAG + ".tar"
build:
go build -o build/app cmd/app/*.go
run: build
./build/app
docker-build: build
podman build -t {{IMAGE_NAME}} .
image: docker-build
mkdir -p image/
if [ -f image/{{TAR_NAME}} ]; then rm image/{{TAR_NAME}}; fi
podman save -o image/{{TAR_NAME}} {{IMAGE_NAME}}
clean:
rm -rf build/
rm -rf image/
Running the steps
To run any step within the Justfile it works just like make instead, you
use just:
just build