diff --git a/.github/workflows/release-testnet-faucet-docker.yml b/.github/workflows/release-testnet-faucet-docker.yml new file mode 100644 index 00000000..2f6ded08 --- /dev/null +++ b/.github/workflows/release-testnet-faucet-docker.yml @@ -0,0 +1,60 @@ +# This job builds and publishes a docker image for the gallery dApp to +# the dockerhub image repository. +name: Create and publish a Docker image for the testnet faucet dApp. + +on: + workflow_dispatch: # allows manual trigger + + push: + tags: + - 'testnet-faucet/*.*.*' + +env: + REGISTRY: docker.io + IMAGE_NAME: dapp-testnet-faucet + EXPECTED_TAG: ${{ github.ref_name }} + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + environment: testnet-faucet + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: recursive + # Uses the `docker/login-action` action to log in to the Container registry. + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Extract tag from package.json + id: meta + run: | + export VERSION=$(jq -r .version testnet-faucet/package.json) + export FULL_IMAGE_TAG="${{ env.REGISTRY }}/concordium/$IMAGE_NAME:$VERSION" + echo "::notice FULL_IMAGE_TAG=${FULL_IMAGE_TAG}" + Make sure the image does not exist. Abort if we can retrieve any metadata. + if docker manifest inspect ${FULL_IMAGE_TAG} > /dev/null; then + echo "::error ${FULL_IMAGE_TAG} already exists" + exit 1 + elif [ ! "${EXPECTED_TAG}" = "testnet-faucet/${VERSION}" ]; then + echo "::error Expected tag ${EXPECTED_TAG} does not match the version ${VERSION}." + exit 1 + else + # Store the full image tag into a tag variable for the following step. + echo "tag=${FULL_IMAGE_TAG}" > "$GITHUB_OUTPUT" + fi + - name: Prepare .env file + run: | + echo "${{ vars.TESTNET_FAUCET_NEXT_PUBLIC }}" > ./testnet-faucet/.env + - name: Build and push Docker image + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + context: testnet-faucet + file: testnet-faucet/Dockerfile + push: true + platforms: linux/amd64 + tags: ${{ steps.meta.outputs.tag }} diff --git a/testnet-faucet/Dockerfile b/testnet-faucet/Dockerfile new file mode 100644 index 00000000..f166a892 --- /dev/null +++ b/testnet-faucet/Dockerfile @@ -0,0 +1,59 @@ +# Based on: +# - https://nextjs.org/docs/app/building-your-application/deploying +# - https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile +FROM node:20-alpine AS base + +# Install dependencies only when needed +FROM base AS deps +# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. +RUN apk add --no-cache libc6-compat +WORKDIR /app + +# Install dependencies based on the preferred package manager +COPY package.json yarn.lock* ./ +RUN yarn --frozen-lockfile + +# Rebuild the source code only when needed +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Next.js collects completely anonymous telemetry data about general usage. +# Learn more here: https://nextjs.org/telemetry +# Uncomment the following line in case you want to disable telemetry during the build. +# ENV NEXT_TELEMETRY_DISABLED 1 + +RUN yarn run build + +# Production image, copy all the files and run next +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV production +# Uncomment the following line in case you want to disable telemetry during runtime. +# ENV NEXT_TELEMETRY_DISABLED 1 + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +COPY --from=builder /app/public ./public + +# Set the correct permission for prerender cache +RUN mkdir .next +RUN chown nextjs:nodejs .next + +# Automatically leverage output traces to reduce image size +# https://nextjs.org/docs/advanced-features/output-file-tracing +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +ENV PORT=3000 + +# server.js is created by next build from the standalone output +# https://nextjs.org/docs/pages/api-reference/next-config-js/output +CMD HOSTNAME="0.0.0.0" node server.js diff --git a/testnet-faucet/next.config.mjs b/testnet-faucet/next.config.mjs index bbde6fbc..97c630e7 100644 --- a/testnet-faucet/next.config.mjs +++ b/testnet-faucet/next.config.mjs @@ -1,6 +1,7 @@ /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, + output: 'standalone', }; export default nextConfig;