feat: add docker auto-builds (#461)

https://github.com/codex-storage/nim-codex/issues/412
This commit is contained in:
Slava 2023-07-04 14:46:49 +03:00 committed by GitHub
parent 04ea8c36bf
commit f053135f68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 243 additions and 339 deletions

View File

@ -1,125 +1,154 @@
name: docker
name: Docker
on:
push:
branches:
- "main"
- master
tags:
- "v*.*.*"
paths-ignore:
- '**/*.md'
- '.gitignore'
- '.github/**'
- '!.github/workflows/docker.yml'
- 'docker/**'
- '!docker/codex.Dockerfile'
- '!docker/docker-entrypoint.sh'
workflow_dispatch:
env:
DOCKER_FILE: docker/codex.Dockerfile
DOCKER_REPO: codexstorage/nim-codex
MAKE_PARALLEL: 4
jobs:
docker-amd64:
# Build platform specific image
build:
strategy:
fail-fast: true
matrix:
target:
- os: linux
arch: amd64
- os: linux
arch: arm64
include:
- target:
os: linux
arch: amd64
builder: ubuntu-22.04
- target:
os: linux
arch: arm64
builder: buildjet-4vcpu-ubuntu-2204-arm
name: Build ${{ matrix.target.os }}/${{ matrix.target.arch }}
runs-on: ${{ matrix.builder }}
outputs:
tags-linux-amd64: ${{ steps.tags.outputs.tags-linux-amd64 }}
tags-linux-arm64: ${{ steps.tags.outputs.tags-linux-arm64 }}
env:
PLATFORM: ${{ format('{0}/{1}', 'linux', matrix.target.arch) }}
SUFFIX: ${{ format('{0}-{1}', 'linux', matrix.target.arch) }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Docker - Meta
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.DOCKER_REPO }}
flavor: |
latest=false
tags: |
type=semver,pattern={{version}},suffix=-${{ env.SUFFIX }}
type=sha,suffix=-${{ env.SUFFIX }},enable=${{ !startsWith(github.ref, 'refs/tags/') }}
- name: Docker - Set tags output
id: tags
run: |
if [[ '${{ matrix.target.os }}' == 'linux' && '${{ matrix.target.arch }}' == 'amd64' ]]; then
echo "tags-linux-amd64=${{ steps.meta.outputs.tags }}" >> "$GITHUB_OUTPUT"
elif [[ '${{ matrix.target.os }}' == 'linux' && '${{ matrix.target.arch }}' == 'arm64' ]]; then
echo "tags-linux-arm64=${{ steps.meta.outputs.tags }}" >> "$GITHUB_OUTPUT"
fi
- name: Docker - Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Docker - Build and export to Docker
uses: docker/build-push-action@v4
with:
context: .
file: ${{ env.DOCKER_FILE }}
platforms: ${{ env.PLATFORM }}
build-args: |
MAKE_PARALLEL=${{ env.MAKE_PARALLEL }}
load: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Docker - Minify image
uses: kitabisa/docker-slim-action@v1
id: slim
env:
DSLIM_HTTP_PROBE: false
with:
target: ${{ steps.meta.outputs.tags }}
overwrite: true
- name: Docker - Show slim report
run: echo "${REPORT}" | jq -r
env:
REPORT: ${{ steps.slim.outputs.report }}
- name: Docker - Push to Docker registry
uses: docker/build-push-action@v4
with:
context: .
file: ${{ env.DOCKER_FILE }}
platforms: ${{ env.PLATFORM }}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# Publish single image
publish:
name: Push single image
runs-on: ubuntu-latest
needs: build
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Docker meta
- name: Docker - Meta
id: meta
uses: docker/metadata-action@v4
with:
images: thatbenbierens/nim-codex-amd64
images: ${{ env.DOCKER_REPO }}
tags: |
type=semver,pattern={{version}}
type=sha
type=sha,enable=${{ !startsWith(github.ref, 'refs/tags/') }}
- name: Login to Docker Hub
if: github.event_name != 'pull_request'
- name: Docker - Set tags
run: |
# Transform multi-line tags in to the comma-seperated
TAGS=$(echo "${{ steps.meta.outputs.tags }}" | tr '\n' ',' | awk '{gsub(/,$/,"");}1')
echo "TAGS=${TAGS}" >>$GITHUB_ENV
- name: Docker - Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and export to Docker
id: build
uses: docker/build-push-action@v4
- name: Docker - Create and push manifest images
uses: Noelware/docker-manifest-action@master
with:
context: .
file: docker/codex.Dockerfile
platforms: linux/amd64
load: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Minify docker image
uses: kitabisa/docker-slim-action@v1
env:
DSLIM_HTTP_PROBE: false
with:
target: ${{ steps.meta.outputs.tags }}
overwrite: true
- name: Show slim report
run: echo "${{ steps.slim.outputs.report }}"
- name: Push to Docker registry
if: github.event_name != 'pull_request'
id: push
uses: docker/build-push-action@v4
with:
context: .
file: docker/codex.Dockerfile
platforms: linux/amd64
inputs: ${{ env.TAGS }}
images: ${{ needs.build.outputs.tags-linux-amd64 }},${{ needs.build.outputs.tags-linux-arm64 }}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
docker-arm64:
runs-on: buildjet-4vcpu-ubuntu-2204-arm
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: thatbenbierens/nim-codex-arm64
tags: |
type=semver,pattern={{version}}
type=sha
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and export to Docker
id: build
uses: docker/build-push-action@v4
with:
context: .
file: docker/codex.Dockerfile
platforms: linux/arm64
load: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Minify docker image
uses: kitabisa/docker-slim-action@v1
env:
DSLIM_HTTP_PROBE: false
with:
target: ${{ steps.meta.outputs.tags }}
overwrite: true
- name: Show slim report
run: echo "${{ steps.slim.outputs.report }}"
- name: Push to Docker registry
if: github.event_name != 'pull_request'
id: push
uses: docker/build-push-action@v4
with:
context: .
file: docker/codex.Dockerfile
platforms: linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@ -1,61 +1,48 @@
# Codex Docker Image
Build and run using the example docker-compose file:
`docker-compose up -d`
Codex provides pre-built docker images and they are stored in the [codexstorage/nim-codex](https://hub.docker.com/repository/docker/codexstorage/nim-codex) repository.
Stop and retain image and volume data:
`docker-compose down`
Stop and delete image and volume data:
`docker-compose down --rmi all -v`
`rm -R hostdatadir`
## Run
# Environment variables
Codex docker image supports the following environment variables:
- LISTEN_ADDRS(*)
- API_BINDADDR(*)
- DATA_DIR(*)
- LOG_LEVEL
- METRICS_ADDR
- METRICS_PORT
- NAT_IP
- API_PORT
- DISC_IP
- DISC_PORT
- NET_PRIVKEY
- BOOTSTRAP_SPR
- MAX_PEERS
- AGENT_STRING
- STORAGE_QUOTA
- BLOCK_TTL
- CACHE_SIZE
- ETH_PROVIDER
- ETH_ACCOUNT
- ETH_DEPLOYMENT
- SIMULATE_PROOF_FAILURES
- VALIDATOR
- PERSISTENCE
- CODEX_NODENAME(†)
We can run Codex Docker image using CLI
```shell
# Default run
docker run --rm codexstorage/nim-codex
(*) These variables have default values in the docker image that are different from Codex's standard default values.
# Mount local datadir
docker run -v ./datadir:/datadir --rm codexstorage/nim-codex codex --data-dir=/datadir
```
(†) CODEX_NODENAME is used for logging purposes only in the docker image
And Docker Compose
```shell
# Run in detached mode
docker-compose up -d
```
All environment variables are optional and will default to Codex's CLI default values.
# Constants
Codex CLI arguments 'data-dir', 'listen-addrs', and 'api-bindaddr' cannot be configured. They are set to values required for docker in case of bind addresses. In the case of 'data-dir', the value is set to `/datadir`. It is important that you map this folder to a host volume in your container configuration. See docker-compose.yaml for examples.
## Arguments
# Useful
Connect nodes with the `/connect` endpoint.
To get the IP address of a container within a network:
Find container Id: `docker ps`
Open terminal in container: `docker exec -it <CONTAINER ID> sh`
Get IP addresses: `ifconfig`
Docker image is based on the [codex.Dockerfile](codex.Dockerfile) and there is
```
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["codex"]
```
# Slim
It means that at the image run it will just run `codex` application without any arguments and we can pass them as a regular arguments, by overriding command
```shell
docker run codexstorage/nim-codex codex --api-bindaddr=0.0.0.0
```
## Environment variables
We can configure Codex using [Environment variables](../README#environment-variables) and [docker-compose.yaml](docker-compose.yaml) file can be useful as an example.
## Slim
1. Build the image using `docker build -t status-im/codexsetup:latest -f codex.Dockerfile ..`
2. The docker image can then be minifed using [slim](https://github.com/slimtoolkit/slim). Install slim on your path and then run:
2. The docker image can then be minified using [slim](https://github.com/slimtoolkit/slim). Install slim on your path and then run:
```shell
slim # brings up interactive prompt
>>> build --target status-im/codexsetup --http-probe-off true

View File

@ -1,18 +1,35 @@
FROM ubuntu:lunar-20230415 AS builder
# Variables
ARG BUILDER=ubuntu:lunar-20230415
ARG IMAGE=${BUILDER}
ARG BUILD_HOME=/src
ARG MAKE_PARALLEL=${MAKE_PARALLEL:-4}
ARG MAKE_PARAMS=${MAKE_PARAMS:-NIM_PARAMS="-d:disableMarchNative"}
ARG APP_HOME=/codex
# Build
FROM ${BUILDER} AS builder
ARG BUILD_HOME
ARG MAKE_PARALLEL
ARG MAKE_PARAMS
RUN apt-get update && apt-get install -y git cmake curl make bash lcov build-essential nim
RUN echo 'export NIMBLE_DIR="${HOME}/.nimble"' >> "${HOME}/.bash_env"
RUN echo 'export PATH="${NIMBLE_DIR}/bin:${PATH}"' >> "${HOME}/.bash_env"
WORKDIR /src
WORKDIR ${BUILD_HOME}
COPY . .
RUN make clean
RUN make -j4 update
RUN make -j4 NIM_PARAMS="-d:disableMarchNative -d:codex_enable_api_debug_peers=true"
RUN make -j ${MAKE_PARALLEL} update
RUN make -j ${MAKE_PARALLEL} ${MAKE_PARAMS}
FROM ubuntu:lunar-20230415
WORKDIR /root
RUN apt-get update && apt-get install -y libgomp1 bash net-tools
COPY --from=builder /src/build/codex ./
COPY --from=builder /src/docker/startCodex.sh ./
RUN chmod +x ./startCodex.sh
CMD ["/bin/bash", "-l", "-c", "./startCodex.sh"]
# Create
FROM ${IMAGE}
ARG BUILD_HOME
ARG APP_HOME
WORKDIR ${APP_HOME}
COPY --from=builder ${BUILD_HOME}/build/codex /usr/local/bin
COPY --chmod=0755 docker/docker-entrypoint.sh /
RUN apt-get update && apt-get install -y libgomp1 bash && rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["codex"]

View File

@ -1,27 +1,43 @@
services:
codex-node1:
image: status-im/codexsetup.slim:latest
ports:
- 8080:8080
# Available environment variables:
image: codexstorage/nim-codex:sha-82b0399
environment:
- LOG_LEVEL=TRACE
- METRICS_ADDR=0.0.0.0
- METRICS_PORT=9090
- NAT_IP=2.3.4.5
- API_PORT=8080
- DISC_IP=3.4.5.6
- DISC_PORT=8765
- NET_PRIVKEY=privkey
- BOOTSTRAP_SPR=bootstrap_record
- MAX_PEERS=123
- AGENT_STRING=agent_string
- STORAGE_QUOTA=123456789
- BLOCK_TTL=23456
- CACHE_SIZE=6543
- ETH_PROVIDER=eth
- ETH_ACCOUNT=account
- ETH_MARKETPLACE_ADDRESS=0x59b670e9fA9D0A427751Af201D676719a970857b
- SIMULATE_PROOF_FAILURES=2
- CODEX_LOG_LEVEL=${CODEX_LOG_LEVEL:-TRACE}
- CODEX_METRICS=${CODEX_METRICS:-false}
- CODEX_METRICS_ADDRESS=${CODEX_METRICS_ADDRESS:-0.0.0.0}
- CODEX_METRICS_PORT=${CODEX_METRICS_PORT:-8008}
- CODEX_DATA_DIR=${CODEX_DATA_DIR:-/datadir}
- CODEX_LISTEN_ADDRS=${CODEX_LISTEN_ADDRS:-/ip4/0.0.0.0/tcp/2345}
- CODEX_NAT=${CODEX_NAT:-10.0.0.10}
- CODEX_DISC_IP=${CODEX_DISC_IP:-0.0.0.0}
- CODEX_DISC_PORT=${CODEX_DISC_PORT:-8090}
- CODEX_NET_PRIVKEY=${CODEX_NET_PRIVKEY:-key}
# - CODEX_BOOTSTRAP_NODE=${CODEX_BOOTSTRAP_NODE}
- CODEX_MAX_PEERS=${CODEX_MAX_PEERS:-160}
- CODEX_AGENT_STRING=${CODEX_AGENT_STRING:-Codex}
- CODEX_API_BINDADDR=${CODEX_API_BINDADDR:-127.0.0.1}
- CODEX_API_PORT=${CODEX_API_PORT:-8080}
- CODEX_REPO_KIND=${CODEX_REPO_KIND:-fs}
- CODEX_STORAGE_QUOTA=${CODEX_STORAGE_QUOTA:-8589934592}
- CODEX_BLOCK_TTL=${CODEX_BLOCK_TTL:-0}
# - CODEX_BLOCK_MI=${CODEX_BLOCK_MI}
- CODEX_BLOCK_MN=${CODEX_BLOCK_MN:-1000}
- CODEX_CACHE_SIZE=${CODEX_CACHE_SIZE:-0}
- CODEX_PERSISTENCE=${CODEX_PERSISTENCE:-false}
- CODEX_ETH_PROVIDER=${CODEX_ETH_PROVIDER:-ws://localhost:8545}
# - CODEX_ETH_ACCOUNT=${CODEX_ETH_ACCOUNT}
# - CODEX_MARKETPLACE_ADDRESS=${CODEX_MARKETPLACE_ADDRESS:-0x59b670e9fA9D0A427751Af201D676719a970857b}
- CODEX_VALIDATOR=${CODEX_VALIDATOR:-false}
- CODEX_VALIDATOR_MAX_SLOTS=${CODEX_VALIDATOR_MAX_SLOTS:-1000}
ports:
- 8080:8080/tcp # REST API
- 8008:8008/tcp # Metrics
- 2345:2345/tcp # libp2p
- 8090:8090/udp # DHT discovery
volumes:
- /datadir:/datadir
networks:
- codex
networks:
codex:
driver: bridge

View File

@ -0,0 +1,5 @@
#!/bin/bash
# Run
echo "Run Codex node"
exec "$@"

View File

@ -1,150 +0,0 @@
NAME=""
if [ -n "$CODEX_NODENAME" ]; then
NAME=" '$CODEX_NODENAME'"
fi
echo "Starting Codex node$NAME"
args=""
## Using local ip as NAT
nat_addr=$(ifconfig eth0 | awk '/inet/ {gsub("addr:", "", $2); print $2}')
echo "Local IP: $nat_addr"
# Required arguments
if [ -n "$LISTEN_ADDRS" ]; then
echo "Listen address: $LISTEN_ADDRS"
args="$args --listen-addrs=$LISTEN_ADDRS"
else
args="$args --listen-addrs=/ip4/0.0.0.0/tcp/8071"
fi
if [ -n "$API_BINDADDR" ]; then
echo "API bind address: $API_BINDADDR"
args="$args --api-bindaddr=$API_BINDADDR"
else
args="$args --api-bindaddr=0.0.0.0"
fi
if [ -n "$DATA_DIR" ]; then
echo "Data dir: $DATA_DIR"
args="$args --data-dir=$DATA_DIR"
else
args="$args --data-dir=/datadir"
fi
# Optional arguments
# Log level
if [ -n "$LOG_LEVEL" ]; then
echo "Log level: $LOG_LEVEL"
args="$args --log-level=\"$LOG_LEVEL\""
fi
# Metrics
if [ -n "$METRICS_ADDR" ] && [ -n "$METRICS_PORT" ]; then
echo "Metrics enabled"
args="$args --metrics=true"
args="$args --metrics-address=$METRICS_ADDR"
args="$args --metrics-port=$METRICS_PORT"
fi
# NAT
echo "NAT: $nat_addr"
args="$args --nat=$nat_addr"
# Discovery IP
if [ -n "$DISC_IP" ]; then
echo "Discovery IP: $DISC_IP"
args="$args --disc-ip=$DISC_IP"
fi
# Discovery Port
if [ -n "$DISC_PORT" ]; then
echo "Discovery Port: $DISC_PORT"
args="$args --disc-port=$DISC_PORT"
fi
# Net private key
if [ -n "$NET_PRIVKEY" ]; then
echo "Network Private Key path: $NET_PRIVKEY"
args="$args --net-privkey=$NET_PRIVKEY"
fi
# Bootstrap SPR
if [ -n "$BOOTSTRAP_SPR" ]; then
echo "Bootstrap SPR: $BOOTSTRAP_SPR"
args="$args --bootstrap-node=$BOOTSTRAP_SPR"
fi
# Max peers
if [ -n "$MAX_PEERS" ]; then
echo "Max peers: $MAX_PEERS"
args="$args --max-peers=$MAX_PEERS"
fi
# Agent string
if [ -n "$AGENT_STRING" ]; then
echo "Agent string: $AGENT_STRING"
args="$args --agent-string=$AGENT_STRING"
fi
# API port
if [ -n "$API_PORT" ]; then
echo "API port: $API_PORT"
args="$args --api-port=$API_PORT"
fi
# Storage quota
if [ -n "$STORAGE_QUOTA" ]; then
echo "Storage quote: $STORAGE_QUOTA"
args="$args --storage-quota=$STORAGE_QUOTA"
fi
# Block TTL
if [ -n "$BLOCK_TTL" ]; then
echo "Block TTL: $BLOCK_TTL"
args="$args --block-ttl=$BLOCK_TTL"
fi
# Cache size
if [ -n "$CACHE_SIZE" ]; then
echo "Cache size: $CACHE_SIZE"
args="$args --cache-size=$CACHE_SIZE"
fi
# Ethereum persistence
if [ -n "$ETH_PROVIDER" ]; then
echo "Provider: $ETH_PROVIDER"
args="$args --eth-provider=$ETH_PROVIDER"
fi
if [ -n "$ETH_ACCOUNT" ]; then
echo "Ethereum account: $ETH_ACCOUNT"
args="$args --eth-account=$ETH_ACCOUNT"
fi
if [ -n "$ETH_MARKETPLACE_ADDRESS" ]; then
echo "Marketplace address: $ETH_MARKETPLACE_ADDRESS"
args="$args --marketplace-address=$ETH_MARKETPLACE_ADDRESS"
fi
if [ -n "$SIMULATE_PROOF_FAILURES" ]; then
echo "Simulate proof failures: $SIMULATE_PROOF_FAILURES"
args="$args --simulate-proof-failures=$SIMULATE_PROOF_FAILURES"
fi
if [ "$PERSISTENCE" = "true" ] || [ "$PERSISTENCE" = "1" ]; then
echo "Persistence enabled"
args="$args --persistence"
else
echo "Persistence disabled"
fi
if [ "$VALIDATOR" = "true" ] || [ "$VALIDATOR" = "1" ]; then
echo "Validator enabled"
args="$args --validator"
else
echo "Validator disabled"
fi
echo "./codex $args"
/bin/bash -l -c "./codex $args"