multi stage Dockerfile and Taskfile (#102)

* multi-stage Dockerfile

* add build arguments for git

* add taskfile

* switch back to copying source into build stage and clean up labels

* get image name from .env

* remove top level ARGs

* update DOCKER-README with Taskfile details

* mention light and safe image

* add a backup task

* add healthcheck

* add logs-folder task

* add warnings to backup task

* allow port overriding in docker compose
This commit is contained in:
Marius Scurtescu 2024-03-07 21:05:23 -08:00 committed by GitHub
parent d9d8bbe93e
commit dc065cc682
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 230 additions and 19 deletions

15
.env.example Normal file
View File

@ -0,0 +1,15 @@
# Use a custom docker image name
# Default: quilibrium
QUILIBRIUM_IMAGE_NAME=
# Use a custom P2P port.
# Default: 8336
QUILIBRIUM_P2P_PORT=
# Use a custom gRPC port.
# Default: 8337
QUILIBRIUM_GRPC_PORT=
# Use a custom REST port.
# Default: 8338
QUILIBRIUM_REST_PORT=

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ ceremony-client
.config* .config*
.DS_Store .DS_Store
*.mprof *.mprof
.env

View File

@ -43,13 +43,51 @@ net.core.wmem_max = 600000000
## Build ## Build
The only requirements are `git` (to checkout the repository) and docker (to build the image and run the container).
Golang does not have to be installed, the docker image build process uses a build stage that provides the
correct Go environment and compiles the node down to one command.
In the repository root folder, where the [Dockerfile](Dockerfile) file is, build the docker image: In the repository root folder, where the [Dockerfile](Dockerfile) file is, build the docker image:
```shell ```shell
docker build --build-arg GIT_COMMIT=$(git log -1 --format=%h) -t quilibrium -t quilibrium:1.2.15 . docker build --build-arg GIT_COMMIT=$(git log -1 --format=%h) -t quilibrium -t quilibrium:1.4.2 .
``` ```
Use latest version instead of `1.2.15`. Use latest version instead of `1.4.2`.
The image that is built is light and safe. It is based on Alpine Linux with the Quilibrium node binary, not the
source code, nor the Go development environment. The image also has the `grpcurl` tool that can be used to
query the gRPC interface.
### Task
You can also use the [Task](https://taskfile.dev/) tool, it a simple build tool that takes care of extracting
parameters, building the image and running the container. The tasks are all defined in [Taskfile.yaml](Taskfile.yaml).
You can optionally create an `.env` file, in the same repository root folder to override specific parameters. Right now
only one optional env var is supported and that is `QUILIBRIUM_IMAGE_NAME`, if you want to change the default
image name from `quilibrium` to something else. If you are pushing your images to Github then you have to follow the
Github naming convention and use a name like `ghcr.io/mscurtescu/ceremonyclient`.
Bellow there are example interaction with `Task`.
The node version is extracted from [node/main.go](node/main.go). This version string is used to tag the image. The git
repo, branch and commit are read throught the `git` command and depend on the current state of your working
directory (one what branch and at what commit you are). These last three values are used to label the image.
List tasks:
```shell
task -l
```
Show what parameters, like image name, version etc, will be used:
```shell
task status
```
Build the image (aka run the `build` task):
```shell
task build
```
## Run ## Run
@ -70,6 +108,38 @@ docker compose up -d
A `.config/` subfolder will be created under the current folder, this is mapped inside the container. A `.config/` subfolder will be created under the current folder, this is mapped inside the container.
Make sure you backup `config.yml` and `keys.yml`. Make sure you backup `config.yml` and `keys.yml`.
### Task
Similarly to building the image you can also use `Task`.
Start the container through docker compose:
```shell
task up
```
Show the logs through docker compose:
```shell
task logs
```
Drop into a shell inside the running container:
```shell
task shell
```
Stop the running container(s):
```shell
task down
```
Backup the critical configuration:
```shell
task backup
```
The above command will create a `backup.tar.gz` archive in the current folder, you still have to copy this
file from the server into a safe location. The command adds the `config.yml` and `keys.yml` files from
the `.config/` subfolder to the archive, with the ownership of the current user.
### Resource management ### Resource management
To ensure that your client performs optimally within a specific resource configuration, you can specify To ensure that your client performs optimally within a specific resource configuration, you can specify

View File

@ -1,13 +1,4 @@
FROM golang:1.20.14-alpine3.19 FROM golang:1.20.14-alpine3.19 as build
ARG GIT_COMMIT=unspecified
LABEL org.opencontainers.image.title="Quilibrium Network Node"
LABEL org.opencontainers.image.description="Quilibrium is a decentralized alternative to platform as a service providers."
LABEL org.opencontainers.image.vendor=Quilibrium
LABEL org.opencontainers.image.url=https://quilibrium.com/
LABEL org.opencontainers.image.documentation=https://quilibrium.com/docs
LABEL org.opencontainers.image.revision=$GIT_COMMIT
ENV GOEXPERIMENT=arenas ENV GOEXPERIMENT=arenas
@ -17,7 +8,31 @@ COPY . .
WORKDIR /opt/ceremonyclient/node WORKDIR /opt/ceremonyclient/node
RUN go mod download && go mod verify RUN go install ./...
RUN go build ./... RUN go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
ENTRYPOINT ["go", "run", "./..."] FROM alpine:3.19
ARG GIT_REPO
ARG GIT_BRANCH
ARG GIT_COMMIT
ENV GOEXPERIMENT=arenas
LABEL org.opencontainers.image.title="Quilibrium Network Node"
LABEL org.opencontainers.image.description="Quilibrium is a decentralized alternative to platform as a service providers."
LABEL org.opencontainers.image.vendor=Quilibrium
LABEL org.opencontainers.image.url=https://quilibrium.com/
LABEL org.opencontainers.image.documentation=https://quilibrium.com/docs
LABEL org.opencontainers.image.source=$GIT_REPO
LABEL org.opencontainers.image.ref.name=$GIT_BRANCH
LABEL org.opencontainers.image.revision=$GIT_COMMIT
COPY --from=build /go/bin/node /usr/local/bin
COPY --from=build /go/bin/grpcurl /usr/local/bin
COPY --from=build /opt/ceremonyclient/node/ceremony.json /root
COPY --from=build /opt/ceremonyclient/node/retroactive_peers.json /root
WORKDIR /root
ENTRYPOINT ["node"]

105
Taskfile.yaml Normal file
View File

@ -0,0 +1,105 @@
# https://taskfile.dev
version: '3'
dotenv:
- '.env'
vars:
VERSION:
sh: cat node/main.go | grep "Quilibrium Node - v" | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+'
PROJECT_NAME: quilibrium
SERVICE_NAME: node
GIT_REPO:
sh: git config --get remote.origin.url
GIT_BRANCH:
sh: git rev-parse --abbrev-ref HEAD
GIT_COMMIT:
sh: git log -1 --format=%h
tasks:
status:
desc: Display configuration info.
cmds:
- echo -n "Image name:" && echo " ${QUILIBRIUM_IMAGE_NAME:-quilibrium}"
- echo -n "Version :" && echo " {{.VERSION}}"
- echo -n "Repo :" && echo " {{.GIT_REPO}}"
- echo -n "Branch :" && echo " {{.GIT_BRANCH}}"
- echo -n "Commit :" && echo " {{.GIT_COMMIT}}"
silent: true
build:
desc: Build the Quilibrium docker image, unless it is already built.
cmds:
- |
docker build \
--build-arg GIT_REPO={{.GIT_REPO}} \
--build-arg GIT_BRANCH={{.GIT_BRANCH}} \
--build-arg GIT_COMMIT={{.GIT_COMMIT}} \
-t ${QUILIBRIUM_IMAGE_NAME:-quilibrium}:{{.VERSION}} \
-t ${QUILIBRIUM_IMAGE_NAME:-quilibrium}:latest \
.
status:
- |
docker image inspect \
${QUILIBRIUM_IMAGE_NAME:-quilibrium}:{{.VERSION}} \
>/dev/null 2>/dev/null
up:
desc: Run a new Quilibrium container, through docker compose.
cmds:
- docker compose up -d
down:
desc: Take down the Quilibrium container, through docker compose.
cmds:
- docker compose down
shell:
desc: Drop into a shell inside the running container.
cmds:
- docker compose exec -it {{.SERVICE_NAME}} sh
logs:
desc: Print the logs of the running Quilibrium container.
cmds:
- docker compose logs
logs-folder:
desc: Show where Docker stores the logs for the Quilibrium node. You need root permissions to access the folder.
cmds:
- "docker container inspect {{.PROJECT_NAME}}-{{.SERVICE_NAME}}-1 | grep LogPath | cut -d : -f 2 | cut -d '\"' -f 2 | xargs dirname"
backup:
desc: Create a backup file with the critical configuration files.
prompt: You will be prompted for root access. Make sure you verify the generated backup file. Continue?
sources:
- '.config/config.yml'
- '.config/keys.yml'
outputs:
- 'backup.tar.gz'
cmds:
- |
export TMP_DIR=$(mktemp -d)
export TASK_DIR=$(pwd)
sudo cp .config/config.yml $TMP_DIR
sudo cp .config/keys.yml $TMP_DIR
sudo chown $(whoami):$(id -gn) $TMP_DIR/*
cd $TMP_DIR
tar -czf $TASK_DIR/backup.tar.gz *
cd $TASK_DIR
sudo rm -rf $TMP_DIR
echo "Backup saved to: backup.tar.gz"
echo "Do not assume you have a backup unless you verify it!!!"
silent: true
github:login:
desc: Login to GitHub container registry.
cmds:
- echo $GITHUB_TOKEN | docker login ghcr.io -u $GITHUB_USERNAME --password-stdin
push:
desc: Push Quilibrium docker image to the container registry.
cmds:
- docker push ${QUILIBRIUM_IMAGE_NAME:-quilibrium}:{{.VERSION}}
- docker push ${QUILIBRIUM_IMAGE_NAME:-quilibrium}:latest

View File

@ -7,8 +7,7 @@ name: quilibrium
services: services:
node: node:
build: ./ image: ${QUILIBRIUM_IMAGE_NAME:-quilibrium}
image: quilibrium
restart: unless-stopped restart: unless-stopped
deploy: deploy:
resources: resources:
@ -22,9 +21,15 @@ services:
- DEFAULT_LISTEN_REST_MULTIADDR=/ip4/0.0.0.0/tcp/8338 - DEFAULT_LISTEN_REST_MULTIADDR=/ip4/0.0.0.0/tcp/8338
- DEFAULT_STATS_MULTIADDR=/dns/stats.quilibrium.com/tcp/443 - DEFAULT_STATS_MULTIADDR=/dns/stats.quilibrium.com/tcp/443
ports: ports:
- '8336:8336/udp' # p2p - '${QUILIBRIUM_P2P_PORT:-8336}:8336/udp' # p2p
- '127.0.0.1:8337:8337/tcp' # gRPC - '127.0.0.1:${QUILIBRIUM_GRPC_PORT:-8337}:8337/tcp' # gRPC
- '127.0.0.1:8338:8338/tcp' # REST - '127.0.0.1:${QUILIBRIUM_REST_PORT:-8338}:8338/tcp' # REST
healthcheck:
test: ["CMD", "node", "--peer-id"]
interval: 30s
timeout: 5s
retries: 3
start_period: 1m
volumes: volumes:
- ./.config:/opt/ceremonyclient/node/.config - ./.config:/opt/ceremonyclient/node/.config
logging: logging: