diff --git a/.dockerignore b/.dockerignore index 12a78c0d7..12057f20a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,11 +1,11 @@ -# Before the docker CLI sends the context to the docker daemon, it looks for a file -# named .dockerignore in the root directory of the context. If this file exists, the -# CLI modifies the context to exclude files and directories that match patterns in it. +# Before the docker CLI sends the context to the docker daemon, it looks for a file +# named .dockerignore in the root directory of the context. If this file exists, the +# CLI modifies the context to exclude files and directories that match patterns in it. # -# You may want to specify which files to include in the context, rather than which -# to exclude. To achieve this, specify * as the first pattern, followed by one or +# You may want to specify which files to include in the context, rather than which +# to exclude. To achieve this, specify * as the first pattern, followed by one or # more ! exception patterns. -# +# # https://docs.docker.com/engine/reference/builder/#dockerignore-file # Exclude everything: @@ -21,3 +21,4 @@ !zebra-* !zebrad !docker/entrypoint.sh +!docker/runtime-entrypoint.sh diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml index 6131b2d0a..bcb8dc8ad 100644 --- a/.github/workflows/build-docker-image.yml +++ b/.github/workflows/build-docker-image.yml @@ -6,9 +6,6 @@ on: network: required: false type: string - checkpoint_sync: - required: false - type: boolean image_name: required: true type: string @@ -53,6 +50,11 @@ on: tag_suffix: required: false type: string + no_cache: + description: 'Disable the Docker cache for this build' + required: false + type: boolean + default: false outputs: image_digest: @@ -158,19 +160,20 @@ jobs: RUST_LIB_BACKTRACE=${{ inputs.rust_lib_backtrace }} COLORBT_SHOW_HIDDEN=${{ inputs.colorbt_show_hidden }} ZEBRA_SKIP_IPV6_TESTS=${{ inputs.zebra_skip_ipv6_tests }} - CHECKPOINT_SYNC=${{ inputs.checkpoint_sync }} RUST_LOG=${{ inputs.rust_log }} FEATURES=${{ inputs.features }} TEST_FEATURES=${{ inputs.test_features }} RPC_PORT=${{ inputs.rpc_port }} push: true + # Don't read from the cache if the caller disabled it. + # https://docs.docker.com/engine/reference/commandline/buildx_build/#options + no-cache: ${{ inputs.no_cache }} # To improve build speeds, for each branch we push an additional image to the registry, # to be used as the caching layer, using the `max` caching mode. # - # We use multiple cache sources to confirm a cache hit, starting from a per-branch cache, - # and if there's no hit, then continue with the `main` branch. When changes are added to a PR, - # they are usually smaller than the diff between the PR and `main` branch. So this provides the - # best performance. + # We use multiple cache sources to confirm a cache hit, starting from a per-branch cache. + # If there's no hit, we continue with a `main` branch cache, which helps us avoid + # rebuilding cargo-chef, most dependencies, and possibly some Zebra crates. # # The caches are tried in top-down order, the first available cache is used: # https://github.com/moby/moby/pull/26839#issuecomment-277383550 diff --git a/.github/workflows/continous-delivery.yml b/.github/workflows/continous-delivery.yml index 5a91c4f7d..a8487dc36 100644 --- a/.github/workflows/continous-delivery.yml +++ b/.github/workflows/continous-delivery.yml @@ -2,9 +2,12 @@ name: CD # Ensures that only one workflow task will run at a time. Previous deployments, if # already in process, won't get cancelled. Instead, we let the first to complete -# then queue the latest pending workflow, cancelling any workflows in between +# then queue the latest pending workflow, cancelling any workflows in between. +# +# Since the different event types each use a different Managed Instance Group or instance, +# we can run different event types concurrently. concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} cancel-in-progress: false on: @@ -14,10 +17,14 @@ on: default: 'Mainnet' description: 'Network to deploy: Mainnet or Testnet' required: true - checkpoint_sync: - default: 'true' - description: 'Use as many checkpoints as possible when syncing' - required: true + log_file: + description: 'Log to a file path rather than standard output' + no_cache: + description: 'Disable the Docker cache for this build' + required: false + type: boolean + default: false + push: branches: - main @@ -64,17 +71,18 @@ jobs: dockerfile_path: ./docker/Dockerfile dockerfile_target: runtime image_name: zebrad - # We need to hard-code Mainnet here, because env is not allowed in this context - network: ${{ inputs.network || 'Mainnet' }} - checkpoint_sync: true + no_cache: ${{ inputs.no_cache || false }} + # We hard-code Mainnet here, because the config is modified before running zebrad + network: 'Mainnet' rust_backtrace: '1' zebra_skip_ipv6_tests: '1' rust_log: info - # Test that Zebra works using the default config with the latest Zebra version + # Test that Zebra works using the default config with the latest Zebra version, + # and test reconfiguring the docker image for testnet. test-configuration-file: name: Test Zebra default Docker config file - timeout-minutes: 5 + timeout-minutes: 15 runs-on: ubuntu-latest needs: build steps: @@ -85,32 +93,81 @@ jobs: with: short-length: 7 + # Make sure Zebra can sync at least one full checkpoint on mainnet - name: Run tests using the default config run: | set -ex docker pull ${{ vars.GAR_BASE }}/zebrad@${{ needs.build.outputs.image_digest }} docker run --detach --name default-conf-tests -t ${{ vars.GAR_BASE }}/zebrad@${{ needs.build.outputs.image_digest }} - EXIT_STATUS=$(docker logs --tail all --follow default-conf-tests 2>&1 | grep -q --extended-regexp --max-count=1 -e 'estimated progress to chain tip.*BeforeOverwinter'; echo $?; ) + # show the logs, even if the job times out + docker logs --tail all --follow default-conf-tests | \ + tee --output-error=exit /dev/stderr | \ + grep --max-count=1 --extended-regexp --color=always \ + 'net.*=.*Main.*estimated progress to chain tip.*BeforeOverwinter' docker stop default-conf-tests + # get the exit status from docker + EXIT_STATUS=$( \ + docker wait default-conf-tests || \ + docker inspect --format "{{.State.ExitCode}}" default-conf-tests || \ + echo "missing container, or missing exit status for container" \ + ) docker logs default-conf-tests + echo "docker exit status: $EXIT_STATUS" + if [[ "$EXIT_STATUS" = "137" ]]; then + echo "ignoring expected signal status" + exit 0 + fi exit "$EXIT_STATUS" - # This jobs handles the deployment of a Managed Instance Group (MiG) with 2 nodes in - # the us-central1 region. Two different groups of MiGs are deployed one for pushes to - # the main branch and another for version releases of Zebra + # Make sure Zebra can sync the genesis block on testnet + - name: Run tests using a testnet config + run: | + set -ex + docker pull ${{ vars.GAR_BASE }}/zebrad@${{ needs.build.outputs.image_digest }} + docker run --env "NETWORK=Testnet" --detach --name testnet-conf-tests -t ${{ vars.GAR_BASE }}/zebrad@${{ needs.build.outputs.image_digest }} + # show the logs, even if the job times out + docker logs --tail all --follow testnet-conf-tests | \ + tee --output-error=exit /dev/stderr | \ + grep --max-count=1 --extended-regexp --color=always \ + 'net.*=.*Test.*estimated progress to chain tip.*Genesis' + docker stop testnet-conf-tests + # get the exit status from docker + EXIT_STATUS=$( \ + docker wait testnet-conf-tests || \ + docker inspect --format "{{.State.ExitCode}}" testnet-conf-tests || \ + echo "missing container, or missing exit status for container" \ + ) + docker logs testnet-conf-tests + echo "docker exit status: $EXIT_STATUS" + if [[ "$EXIT_STATUS" = "137" ]]; then + echo "ignoring expected signal status" + exit 0 + fi + exit "$EXIT_STATUS" + + # Deploy Managed Instance Groups (MiGs) for Mainnet and Testnet, + # with one node in the configured GCP region. # - # Once this workflow is triggered the previous MiG is replaced, on pushes to main its - # always replaced, and with releases its only replaced if the same major version is - # being deployed, otherwise a new major version is deployed + # Separate Mainnet and Testnet MiGs are deployed whenever there are: + # - pushes to the main branch, or + # - version releases of Zebra. + # + # Once this workflow is triggered: + # - by pushes to main: the MiG is always replaced, + # - by releases: the MiG is only replaced if the same major version is being deployed, + # otherwise a new major version is deployed in a new MiG. # # Runs: # - on every push/merge to the `main` branch # - on every release, when it's published deploy-nodes: - name: Deploy ${{ inputs.network || 'Mainnet' }} nodes + strategy: + matrix: + network: [Mainnet, Testnet] + name: Deploy ${{ matrix.network }} nodes needs: [ build, test-configuration-file, versioning ] runs-on: ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 60 permissions: contents: 'read' id-token: 'write' @@ -129,12 +186,12 @@ jobs: # Makes the Zcash network name lowercase. # # Labels in GCP are required to be in lowercase, but the blockchain network - # uses sentence case, so we need to downcase ${{ inputs.network || 'Mainnet' }}. + # uses sentence case, so we need to downcase the network. # # Passes the lowercase network to subsequent steps using $NETWORK env variable. - name: Downcase network name for labels run: | - NETWORK_CAPS="${{ inputs.network || 'Mainnet' }}" + NETWORK_CAPS="${{ matrix.network }}" echo "NETWORK=${NETWORK_CAPS,,}" >> "$GITHUB_ENV" # Setup gcloud CLI @@ -151,15 +208,18 @@ jobs: # TODO we should implement the fixes from https://github.com/ZcashFoundation/zebra/pull/5670 here # but the implementation is failing as it's requiring the disk names, contrary to what is stated in the official documentation - - name: Create instance template + - name: Create instance template for ${{ matrix.network }} run: | - gcloud compute instance-templates create-with-container zebrad-${{ needs.versioning.outputs.major_version || env.GITHUB_REF_SLUG_URL }}-${{ env.GITHUB_SHA_SHORT }} \ + gcloud compute instance-templates create-with-container zebrad-${{ needs.versioning.outputs.major_version || env.GITHUB_REF_SLUG_URL }}-${{ env.GITHUB_SHA_SHORT }}-${NETWORK} \ --boot-disk-type=pd-ssd \ --image-project=cos-cloud \ --image-family=cos-stable \ + --user-output-enabled \ + --metadata google-logging-enabled=true,google-logging-use-fluentbit=true \ --container-image ${{ vars.GAR_BASE }}/zebrad@${{ needs.build.outputs.image_digest }} \ - --create-disk=name=zebrad-cache-${{ env.GITHUB_SHA_SHORT }},auto-delete=yes,size=300GB,type=pd-ssd \ - --container-mount-disk=mount-path="/zebrad-cache",name=zebrad-cache-${{ env.GITHUB_SHA_SHORT }} \ + --container-env "NETWORK=${{ matrix.network }},LOG_FILE=${{ vars.CD_LOG_FILE }},SENTRY_DSN=${{ vars.SENTRY_DSN }},SHORT_SHA=${{ env.GITHUB_SHA_SHORT }}" \ + --create-disk=name=zebrad-cache-${{ env.GITHUB_SHA_SHORT }}-${NETWORK},auto-delete=yes,size=300GB,type=pd-ssd \ + --container-mount-disk=mount-path="/zebrad-cache",name=zebrad-cache-${{ env.GITHUB_SHA_SHORT }}-${NETWORK} \ --machine-type ${{ vars.GCP_SMALL_MACHINE }} \ --network-interface=subnet=${{ vars.GCP_SUBNETWORK }} \ --service-account ${{ vars.GCP_DEPLOYMENTS_SA }} \ @@ -168,34 +228,34 @@ jobs: --tags zebrad # Check if our destination instance group exists already - - name: Check if instance group exists + - name: Check if ${{ matrix.network }} instance group exists id: does-group-exist continue-on-error: true run: | - gcloud compute instance-groups list | grep "zebrad-${{ needs.versioning.outputs.major_version || env.GITHUB_REF_SLUG_URL }}" | grep "${{ vars.GCP_REGION }}" + gcloud compute instance-groups list | grep "zebrad-${{ needs.versioning.outputs.major_version || env.GITHUB_REF_SLUG_URL }}-${NETWORK}" | grep "${{ vars.GCP_REGION }}" # Deploy new managed instance group using the new instance template - - name: Create managed instance group + - name: Create managed instance group for ${{ matrix.network }} if: steps.does-group-exist.outcome == 'failure' run: | gcloud compute instance-groups managed create \ - "zebrad-${{ needs.versioning.outputs.major_version || env.GITHUB_REF_SLUG_URL }}" \ - --template "zebrad-${{ needs.versioning.outputs.major_version || env.GITHUB_REF_SLUG_URL }}-${{ env.GITHUB_SHA_SHORT }}" \ + "zebrad-${{ needs.versioning.outputs.major_version || env.GITHUB_REF_SLUG_URL }}-${NETWORK}" \ + --template "zebrad-${{ needs.versioning.outputs.major_version || env.GITHUB_REF_SLUG_URL }}-${{ env.GITHUB_SHA_SHORT }}-${NETWORK}" \ --health-check zebrad-tracing-filter \ --initial-delay 30 \ --region "${{ vars.GCP_REGION }}" \ --size 1 # Rolls out update to existing group using the new instance template - - name: Update managed instance group + - name: Update managed instance group for ${{ matrix.network }} if: steps.does-group-exist.outcome == 'success' run: | gcloud compute instance-groups managed rolling-action start-update \ - "zebrad-${{ needs.versioning.outputs.major_version || env.GITHUB_REF_SLUG_URL }}" \ - --version template="zebrad-${{ needs.versioning.outputs.major_version || env.GITHUB_REF_SLUG_URL }}-${{ env.GITHUB_SHA_SHORT }}" \ + "zebrad-${{ needs.versioning.outputs.major_version || env.GITHUB_REF_SLUG_URL }}-${NETWORK}" \ + --version template="zebrad-${{ needs.versioning.outputs.major_version || env.GITHUB_REF_SLUG_URL }}-${{ env.GITHUB_SHA_SHORT }}-${NETWORK}" \ --region "${{ vars.GCP_REGION }}" - # This jobs handles the deployment of a single node (1) in the us-central1-a zone + # This jobs handles the deployment of a single node (1) in the configured GCP zone # when an instance is required to test a specific commit # # Runs: @@ -203,7 +263,7 @@ jobs: # # Note: this instances are not automatically replaced or deleted deploy-instance: - name: Deploy single instance + name: Deploy single ${{ inputs.network }} instance needs: [ build, test-configuration-file ] runs-on: ubuntu-latest timeout-minutes: 30 @@ -222,6 +282,17 @@ jobs: with: short-length: 7 + # Makes the Zcash network name lowercase. + # + # Labels in GCP are required to be in lowercase, but the blockchain network + # uses sentence case, so we need to downcase the network. + # + # Passes the lowercase network to subsequent steps using $NETWORK env variable. + - name: Downcase network name for labels + run: | + NETWORK_CAPS="${{ inputs.network }}" + echo "NETWORK=${NETWORK_CAPS,,}" >> "$GITHUB_ENV" + # Setup gcloud CLI - name: Authenticate to Google Cloud id: auth @@ -235,19 +306,22 @@ jobs: uses: google-github-actions/setup-gcloud@v1.1.1 # Create instance template from container image - - name: Manual deploy of a single instance running zebrad + - name: Manual deploy of a single ${{ inputs.network }} instance running zebrad run: | - gcloud compute instances create-with-container "zebrad-${{ env.GITHUB_REF_SLUG_URL }}-${{ env.GITHUB_SHA_SHORT }}" \ + gcloud compute instances create-with-container "zebrad-${{ env.GITHUB_REF_SLUG_URL }}-${{ env.GITHUB_SHA_SHORT }}-${NETWORK}" \ --boot-disk-size 300GB \ --boot-disk-type=pd-ssd \ --image-project=cos-cloud \ --image-family=cos-stable \ + --user-output-enabled \ + --metadata google-logging-enabled=true,google-logging-use-fluentbit=true \ --container-stdin \ --container-tty \ --container-image ${{ vars.GAR_BASE }}/zebrad@${{ needs.build.outputs.image_digest }} \ + --container-env "NETWORK=${{ inputs.network }},LOG_FILE=${{ inputs.log_file || vars.CD_LOG_FILE }},SENTRY_DSN=${{ vars.SENTRY_DSN }},SHORT_SHA=${{ env.GITHUB_SHA_SHORT }}" \ --create-disk=auto-delete=yes,size=300GB,type=pd-ssd \ - --create-disk=name=zebrad-cache-${{ env.GITHUB_SHA_SHORT }},auto-delete=yes,size=300GB,type=pd-ssd \ - --container-mount-disk=mount-path='/zebrad-cache',name=zebrad-cache-${{ env.GITHUB_SHA_SHORT }} \ + --create-disk=name=zebrad-cache-${{ env.GITHUB_SHA_SHORT }}-${NETWORK},auto-delete=yes,size=300GB,type=pd-ssd \ + --container-mount-disk=mount-path='/zebrad-cache',name=zebrad-cache-${{ env.GITHUB_SHA_SHORT }}-${NETWORK} \ --machine-type ${{ vars.GCP_SMALL_MACHINE }} \ --network-interface=subnet=${{ vars.GCP_SUBNETWORK }} \ --service-account ${{ vars.GCP_DEPLOYMENTS_SA }} \ diff --git a/.github/workflows/continous-integration-docker.yml b/.github/workflows/continous-integration-docker.yml index b358da969..2f3063fc6 100644 --- a/.github/workflows/continous-integration-docker.yml +++ b/.github/workflows/continous-integration-docker.yml @@ -14,10 +14,6 @@ on: default: 'Mainnet' description: 'Network to deploy: Mainnet or Testnet' required: true - checkpoint_sync: - default: 'true' - description: 'Configures `zebrad` to use as many checkpoints as possible' - required: true regenerate-disks: type: boolean default: false @@ -33,6 +29,11 @@ on: default: false description: 'Just run a lightwalletd full sync and update tip disks' required: true + no_cache: + description: 'Disable the Docker cache for this build' + required: false + type: boolean + default: false pull_request: paths: @@ -114,8 +115,8 @@ jobs: dockerfile_path: ./docker/Dockerfile dockerfile_target: tests image_name: ${{ vars.CI_IMAGE_NAME }} + no_cache: ${{ inputs.no_cache || false }} network: ${{ inputs.network || vars.ZCASH_NETWORK }} - checkpoint_sync: true rust_backtrace: full rust_lib_backtrace: full colorbt_show_hidden: '1' diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml index 8366f51d2..319777dec 100644 --- a/.github/workflows/release-binaries.yml +++ b/.github/workflows/release-binaries.yml @@ -27,7 +27,6 @@ jobs: dockerfile_target: runtime image_name: zebra network: Mainnet - checkpoint_sync: true rust_backtrace: '1' zebra_skip_ipv6_tests: '1' rust_log: info @@ -48,7 +47,6 @@ jobs: rpc_port: '18232' features: "sentry getblocktemplate-rpcs" test_features: "" - checkpoint_sync: true rust_backtrace: '1' zebra_skip_ipv6_tests: '1' rust_log: info diff --git a/.github/workflows/zcash-params.yml b/.github/workflows/zcash-params.yml index 4574ad1f6..e0b952e33 100644 --- a/.github/workflows/zcash-params.yml +++ b/.github/workflows/zcash-params.yml @@ -9,6 +9,13 @@ concurrency: on: workflow_dispatch: + inputs: + no_cache: + description: 'Disable the Docker cache for this build' + required: false + type: boolean + default: false + push: branches: - 'main' @@ -30,6 +37,7 @@ jobs: dockerfile_path: ./docker/zcash-params/Dockerfile dockerfile_target: release image_name: zcash-params + no_cache: ${{ inputs.no_cache || false }} rust_backtrace: full rust_lib_backtrace: full colorbt_show_hidden: '1' diff --git a/docker/Dockerfile b/docker/Dockerfile index 68d0a95be..012fa674c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,3 +1,5 @@ +# If you want to include a file in the Docker image, add it to .dockerignore. +# # We are using five stages: # - chef: installs cargo-chef # - planner: computes the recipe file @@ -75,10 +77,6 @@ ENV RUST_LOG ${RUST_LOG:-info} ARG ZEBRA_SKIP_IPV6_TESTS ENV ZEBRA_SKIP_IPV6_TESTS ${ZEBRA_SKIP_IPV6_TESTS:-1} -# Use default checkpoint sync and network values if none is provided -ARG CHECKPOINT_SYNC -ENV CHECKPOINT_SYNC ${CHECKPOINT_SYNC:-true} - # Build zebrad with these features # Keep these in sync with: # https://github.com/ZcashFoundation/zebra/blob/main/.github/workflows/build-docker-image.yml#L42 @@ -88,6 +86,7 @@ ARG TEST_FEATURES="lightwalletd-grpc-tests zebra-checkpoints" # separately from the test and production image builds. ENV ENTRYPOINT_FEATURES "$TEST_FEATURES $FEATURES" +# Use default network value if none is provided ARG NETWORK ENV NETWORK ${NETWORK:-Mainnet} @@ -134,74 +133,65 @@ COPY . . # Build zebra RUN cargo build --locked --release --features "${FEATURES}" --package zebrad --bin zebrad +COPY ./docker/runtime-entrypoint.sh / +RUN chmod u+x /runtime-entrypoint.sh + # This stage is only used when deploying nodes or when only the resulting zebrad binary is needed # # To save space, this step starts from scratch using debian, and only adds the resulting # binary from the `release` stage, and the Zcash Sprout & Sapling parameters from ZCash FROM debian:bullseye-slim AS runtime COPY --from=release /opt/zebrad/target/release/zebrad /usr/local/bin +COPY --from=release /runtime-entrypoint.sh / COPY --from=us-docker.pkg.dev/zealous-zebra/zebra/zcash-params /root/.zcash-params /root/.zcash-params RUN apt-get update && \ apt-get install -y --no-install-recommends \ ca-certificates -ARG CHECKPOINT_SYNC=true -ARG NETWORK=Mainnet +# Config settings + +ARG NETWORK +ENV NETWORK ${NETWORK:-Mainnet} + +# Set this to enable the RPC port ARG RPC_PORT +ENV RPC_PORT ${RPC_PORT} -# Use a configurable dir and file for the zebrad configuration file -ARG ZEBRA_CONF_DIR=/etc/zebra -ENV ZEBRA_CONF_DIR ${ZEBRA_CONF_DIR} - -ARG ZEBRA_CONF_FILE=zebrad.toml -ENV ZEBRA_CONF_FILE ${ZEBRA_CONF_FILE} - -ARG ZEBRA_CONF_PATH=${ZEBRA_CONF_DIR}/${ZEBRA_CONF_FILE} -ENV ZEBRA_CONF_PATH ${ZEBRA_CONF_PATH} - -# Build the `zebrad.toml` before starting the container, using the arguments from build -# time, or using the default values set just above. And create the conf path and file if -# it does not exist. -# -# We disable most ports by default, so the default config is secure. -# Users have to opt-in to additional functionality by editing `zebrad.toml`. -# -# It is safe to use multiple RPC threads in Docker, because we know we are the only running -# `zebrad` or `zcashd` process in the container. -# -# TODO: -# - move this file creation to an entrypoint as we can use default values at runtime, -# and modify those as needed when starting the container (at runtime and not at build time) -# - make `cache_dir`, `rpc.listen_addr`, `metrics.endpoint_addr`, and `tracing.endpoint_addr` into Docker arguments -RUN mkdir -p ${ZEBRA_CONF_DIR} \ - && touch ${ZEBRA_CONF_PATH} -RUN set -ex; \ - { \ - echo "[network]"; \ - echo "network = '${NETWORK}'"; \ - echo "listen_addr = '0.0.0.0'"; \ - echo "[consensus]"; \ - echo "checkpoint_sync = ${CHECKPOINT_SYNC}"; \ - echo "[state]"; \ - echo "cache_dir = '/zebrad-cache'"; \ - echo "[rpc]"; \ - [ -n "$RPC_PORT" ] && echo "listen_addr = '0.0.0.0:${RPC_PORT}'"; \ - echo "parallel_cpu_threads = 0"; \ - echo "[metrics]"; \ - echo "#endpoint_addr = '0.0.0.0:9999'"; \ - echo "[tracing]"; \ - echo "#endpoint_addr = '0.0.0.0:3000'"; \ - } > "${ZEBRA_CONF_PATH}" +# Set this to log to a file, if not set, logs to standard output +ARG LOG_FILE +ENV LOG_FILE ${LOG_FILE} +# Expose configured ports EXPOSE 8233 18233 $RPC_PORT -ARG SHORT_SHA -ENV SHORT_SHA $SHORT_SHA +# Config location +# Use a configurable dir and file for the zebrad configuration file +ARG ZEBRA_CONF_DIR +ENV ZEBRA_CONF_DIR ${ZEBRA_CONF_DIR:-/etc/zebra} + +ARG ZEBRA_CONF_FILE +ENV ZEBRA_CONF_FILE ${ZEBRA_CONF_FILE:-zebrad.toml} + +ARG ZEBRA_CONF_PATH +ENV ZEBRA_CONF_PATH ${ZEBRA_CONF_PATH:-$ZEBRA_CONF_DIR/$ZEBRA_CONF_FILE} + +# Other settings + +ARG SHORT_SHA +ENV SHORT_SHA ${SHORT_SHA} + +# Set this to send sentry reports when Zebra crashes ARG SENTRY_DSN ENV SENTRY_DSN ${SENTRY_DSN} -# TODO: remove the specified config file location and use the default expected by zebrad -CMD zebrad -c "${ZEBRA_CONF_PATH}" start +# Create a default config file based on the Docker build arguments, +# and report the available zebrad arguments. +# (--help is used as a dummy command.) +RUN /runtime-entrypoint.sh --help + +# Update the config file based on the Docker run variables, +# and launch zebrad with it +ENTRYPOINT [ "/runtime-entrypoint.sh" ] diff --git a/docker/runtime-entrypoint.sh b/docker/runtime-entrypoint.sh new file mode 100755 index 000000000..a91f4ea21 --- /dev/null +++ b/docker/runtime-entrypoint.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash + +# show the commands we are executing +set -x +# exit if a command fails +set -e +# exit if any command in a pipeline fails +set -o pipefail + +echo "Config variables:" +echo "NETWORK=$NETWORK" +echo "RPC_PORT=$RPC_PORT" +echo "LOG_FILE=$LOG_FILE" + +echo "Config location:" +echo "ZEBRA_CONF_DIR=$ZEBRA_CONF_DIR" +echo "ZEBRA_CONF_FILE=$ZEBRA_CONF_FILE" +echo "ZEBRA_CONF_PATH=$ZEBRA_CONF_PATH" + +echo "Other variables:" +echo "SHORT_SHA=$SHORT_SHA" +echo "SENTRY_DSN=$SENTRY_DSN" + +# Create the conf path and file if it does not exist. +mkdir -p "$ZEBRA_CONF_DIR" +touch "$ZEBRA_CONF_PATH" + +# Populate `zebrad.toml` before starting zebrad, using the environmental +# variables set by the Dockerfile. +# +# We disable most ports by default, so the default config is secure. +# Users have to opt-in to additional functionality by setting environmental variables. +# +# TODO: +# - make `cache_dir`, `metrics.endpoint_addr`, and `tracing.endpoint_addr` into Docker arguments +# - add an $EXTRA_CONFIG or $REPLACEMENT_CONFIG environmental variable +cat < "$ZEBRA_CONF_PATH" +[network] +network = "$NETWORK" +listen_addr = "0.0.0.0" + +[state] +cache_dir = "/zebrad-cache" + +[metrics] +#endpoint_addr = "0.0.0.0:9999" +EOF + +if [[ -n "$RPC_PORT" ]]; then +cat <> "$ZEBRA_CONF_PATH" +[rpc] +listen_addr = "0.0.0.0:${RPC_PORT}" +EOF +fi + +if [[ -n "$LOG_FILE" ]]; then +mkdir -p $(dirname "$LOG_FILE") + +cat <> "$ZEBRA_CONF_PATH" +[tracing] +log_file = "${LOG_FILE}" +#endpoint_addr = "0.0.0.0:3000" +EOF +fi + +echo "Using zebrad.toml:" +cat "$ZEBRA_CONF_PATH" + +exec zebrad -c "$ZEBRA_CONF_PATH" "$@"