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: on:
push: push:
branches: branches:
- "main" - master
tags: tags:
- "v*.*.*" - "v*.*.*"
paths-ignore:
- '**/*.md'
- '.gitignore'
- '.github/**'
- '!.github/workflows/docker.yml'
- 'docker/**'
- '!docker/codex.Dockerfile'
- '!docker/docker-entrypoint.sh'
workflow_dispatch: workflow_dispatch:
env:
DOCKER_FILE: docker/codex.Dockerfile
DOCKER_REPO: codexstorage/nim-codex
MAKE_PARALLEL: 4
jobs: 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 runs-on: ubuntu-latest
needs: build
steps: steps:
- name: Checkout - name: Docker - Meta
uses: actions/checkout@v3
- name: Docker meta
id: meta id: meta
uses: docker/metadata-action@v4 uses: docker/metadata-action@v4
with: with:
images: thatbenbierens/nim-codex-amd64 images: ${{ env.DOCKER_REPO }}
tags: | tags: |
type=semver,pattern={{version}} type=semver,pattern={{version}}
type=sha type=sha,enable=${{ !startsWith(github.ref, 'refs/tags/') }}
- name: Login to Docker Hub - name: Docker - Set tags
if: github.event_name != 'pull_request' 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 uses: docker/login-action@v2
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and export to Docker - name: Docker - Create and push manifest images
id: build uses: Noelware/docker-manifest-action@master
uses: docker/build-push-action@v4
with: with:
context: . inputs: ${{ env.TAGS }}
file: docker/codex.Dockerfile images: ${{ needs.build.outputs.tags-linux-amd64 }},${{ needs.build.outputs.tags-linux-arm64 }}
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
push: true 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,64 +1,51 @@
# Codex Docker Image # Codex Docker Image
Build and run using the example docker-compose file: 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.
`docker-compose up -d`
Stop and retain image and volume data:
`docker-compose down`
Stop and delete image and volume data: ## Run
`docker-compose down --rmi all -v`
`rm -R hostdatadir`
# Environment variables We can run Codex Docker image using CLI
Codex docker image supports the following environment variables: ```shell
- LISTEN_ADDRS(*) # Default run
- API_BINDADDR(*) docker run --rm codexstorage/nim-codex
- 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(†)
(*) 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 ## Arguments
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.
# Useful Docker image is based on the [codex.Dockerfile](codex.Dockerfile) and there is
Connect nodes with the `/connect` endpoint. ```
To get the IP address of a container within a network: ENTRYPOINT ["/docker-entrypoint.sh"]
Find container Id: `docker ps` CMD ["codex"]
Open terminal in container: `docker exec -it <CONTAINER ID> sh` ```
Get IP addresses: `ifconfig`
# 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
1. Build the image using `docker build -t status-im/codexsetup:latest -f codex.Dockerfile ..` ```shell
2. The docker image can then be minifed using [slim](https://github.com/slimtoolkit/slim). Install slim on your path and then run: docker run codexstorage/nim-codex codex --api-bindaddr=0.0.0.0
```shell ```
slim # brings up interactive prompt
>>> build --target status-im/codexsetup --http-probe-off true
``` ## Environment variables
3. This should output an image with name `status-im/codexsetup.slim`
4. We can then bring up the image using `docker-compose up -d`. 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 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
```
3. This should output an image with name `status-im/codexsetup.slim`
4. We can then bring up the image using `docker-compose up -d`.

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 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 NIMBLE_DIR="${HOME}/.nimble"' >> "${HOME}/.bash_env"
RUN echo 'export PATH="${NIMBLE_DIR}/bin:${PATH}"' >> "${HOME}/.bash_env" RUN echo 'export PATH="${NIMBLE_DIR}/bin:${PATH}"' >> "${HOME}/.bash_env"
WORKDIR /src WORKDIR ${BUILD_HOME}
COPY . . COPY . .
RUN make clean RUN make clean
RUN make -j4 update RUN make -j ${MAKE_PARALLEL} update
RUN make -j4 NIM_PARAMS="-d:disableMarchNative -d:codex_enable_api_debug_peers=true" RUN make -j ${MAKE_PARALLEL} ${MAKE_PARAMS}
FROM ubuntu:lunar-20230415 # Create
WORKDIR /root FROM ${IMAGE}
RUN apt-get update && apt-get install -y libgomp1 bash net-tools ARG BUILD_HOME
COPY --from=builder /src/build/codex ./ ARG APP_HOME
COPY --from=builder /src/docker/startCodex.sh ./
RUN chmod +x ./startCodex.sh WORKDIR ${APP_HOME}
CMD ["/bin/bash", "-l", "-c", "./startCodex.sh"] 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: services:
codex-node1: codex-node1:
image: status-im/codexsetup.slim:latest image: codexstorage/nim-codex:sha-82b0399
ports:
- 8080:8080
# Available environment variables:
environment: environment:
- LOG_LEVEL=TRACE - CODEX_LOG_LEVEL=${CODEX_LOG_LEVEL:-TRACE}
- METRICS_ADDR=0.0.0.0 - CODEX_METRICS=${CODEX_METRICS:-false}
- METRICS_PORT=9090 - CODEX_METRICS_ADDRESS=${CODEX_METRICS_ADDRESS:-0.0.0.0}
- NAT_IP=2.3.4.5 - CODEX_METRICS_PORT=${CODEX_METRICS_PORT:-8008}
- API_PORT=8080 - CODEX_DATA_DIR=${CODEX_DATA_DIR:-/datadir}
- DISC_IP=3.4.5.6 - CODEX_LISTEN_ADDRS=${CODEX_LISTEN_ADDRS:-/ip4/0.0.0.0/tcp/2345}
- DISC_PORT=8765 - CODEX_NAT=${CODEX_NAT:-10.0.0.10}
- NET_PRIVKEY=privkey - CODEX_DISC_IP=${CODEX_DISC_IP:-0.0.0.0}
- BOOTSTRAP_SPR=bootstrap_record - CODEX_DISC_PORT=${CODEX_DISC_PORT:-8090}
- MAX_PEERS=123 - CODEX_NET_PRIVKEY=${CODEX_NET_PRIVKEY:-key}
- AGENT_STRING=agent_string # - CODEX_BOOTSTRAP_NODE=${CODEX_BOOTSTRAP_NODE}
- STORAGE_QUOTA=123456789 - CODEX_MAX_PEERS=${CODEX_MAX_PEERS:-160}
- BLOCK_TTL=23456 - CODEX_AGENT_STRING=${CODEX_AGENT_STRING:-Codex}
- CACHE_SIZE=6543 - CODEX_API_BINDADDR=${CODEX_API_BINDADDR:-127.0.0.1}
- ETH_PROVIDER=eth - CODEX_API_PORT=${CODEX_API_PORT:-8080}
- ETH_ACCOUNT=account - CODEX_REPO_KIND=${CODEX_REPO_KIND:-fs}
- ETH_MARKETPLACE_ADDRESS=0x59b670e9fA9D0A427751Af201D676719a970857b - CODEX_STORAGE_QUOTA=${CODEX_STORAGE_QUOTA:-8589934592}
- SIMULATE_PROOF_FAILURES=2 - 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"