From ea7e175fde27616ad38ce1c4972b8b9c1e844792 Mon Sep 17 00:00:00 2001 From: fryd Date: Tue, 30 Aug 2022 10:53:27 +0200 Subject: [PATCH] ci: fix publishing docker images (#1104) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ci: improve GitHub Action to build and publish docker image * ci: increase the timeout for yarn steps * ci: fix build-args * ci: merge build GitHub Workflows into one * ci: add more logging * ci: Pack locally built dist into nginx container * ci: build actual app * ci: setup correct node version * ci: include dist in context * ci: use correct path to determine node version * ci: push images * ci: publish image * ci: login always to the hub * ci: remove debugging conditions Co-authored-by: Mikołaj Młodzikowski --- .dockerignore | 6 +- .github/workflows/publish-containers-cra.yml | 60 --------- .github/workflows/publish-containers-next.yml | 60 --------- .../workflows/publish-docker-containers.yml | 126 ++++++++++++++++++ README.md | 6 +- Dockerfile.cra => dockerfiles/Dockerfile.cra | 4 +- dockerfiles/Dockerfile.cra.dist | 17 +++ .../Dockerfile.next | 4 +- dockerfiles/Dockerfile.next.dist | 16 +++ 9 files changed, 170 insertions(+), 129 deletions(-) delete mode 100644 .github/workflows/publish-containers-cra.yml delete mode 100644 .github/workflows/publish-containers-next.yml create mode 100644 .github/workflows/publish-docker-containers.yml rename Dockerfile.cra => dockerfiles/Dockerfile.cra (82%) create mode 100644 dockerfiles/Dockerfile.cra.dist rename Dockerfile.next => dockerfiles/Dockerfile.next (82%) create mode 100644 dockerfiles/Dockerfile.next.dist diff --git a/.dockerignore b/.dockerignore index 4219dae9f..0916c8ecc 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,5 @@ -dist/* -node_modules/* +apps/**/dist/* +apps/**/node_modules/* tmp/* .dockerignore -Dockerfile +dockerfiles diff --git a/.github/workflows/publish-containers-cra.yml b/.github/workflows/publish-containers-cra.yml deleted file mode 100644 index 4e43e3289..000000000 --- a/.github/workflows/publish-containers-cra.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Publish NextJs containers - -'on': - push: - tags: - - 'v[0-9]+.[0-9]+.[0-9]+' - - 'v[0-9]+.[0-9]+.[0-9]+-pre[0-9]+' - -jobs: - master: - strategy: - matrix: - build-platform: ['linux/amd64'] - app: ['trading'] - name: Build the ${{ inputs.image_name }} image - runs-on: ubuntu-latest - steps: - - name: Set output - id: vars - run: echo ::set-output name=tag::${GITHUB_REF#refs/*/} - - name: Check output - env: - RELEASE_VERSION: ${{ steps.vars.outputs.tag }} - run: | - echo $RELEASE_VERSION - echo ${{ steps.vars.outputs.tag }} - - uses: actions/checkout@v3 - - name: Set up QEMU - id: quemu - uses: docker/setup-qemu-action@v2 - - - name: Setup Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Collect images data - id: tags - run: | - echo '::set-output name=current::vegaprotocol/${{ matrix.app }}:${{ steps.vars.outputs.tag }}' - echo '::set-output name=latest::vegaprotocol/${{ matrix.app }}:latest' - - - name: Echo tags - run: | - echo ${{ steps.tags.outputs.latest }} - echo ${{ steps.tags.outputs.current }} - - - name: Login to DockerHub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Docker build - uses: docker/build-push-action@v3 - with: - context: '.' - file: './Dockerfile.next' - build-args: 'APP=${{ matrix.app }}' - platforms: ${{ matrix.build-platform }} - tags: ${{ steps.tags.outputs.latest }},${{ steps.tags.outputs.current }} - push: true diff --git a/.github/workflows/publish-containers-next.yml b/.github/workflows/publish-containers-next.yml deleted file mode 100644 index 23e726d03..000000000 --- a/.github/workflows/publish-containers-next.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Publish CRA containers - -'on': - push: - tags: - - 'v[0-9]+.[0-9]+.[0-9]+' - - 'v[0-9]+.[0-9]+.[0-9]+-pre[0-9]+' - -jobs: - master: - strategy: - matrix: - build-platform: ['linux/amd64'] - app: ['explorer', 'token'] - name: Build the ${{ inputs.image_name }} image - runs-on: ubuntu-latest - steps: - - name: Set output - id: vars - run: echo ::set-output name=tag::${GITHUB_REF#refs/*/} - - name: Check output - env: - RELEASE_VERSION: ${{ steps.vars.outputs.tag }} - run: | - echo $RELEASE_VERSION - echo ${{ steps.vars.outputs.tag }} - - uses: actions/checkout@v3 - - name: Set up QEMU - id: quemu - uses: docker/setup-qemu-action@v2 - - - name: Setup Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Collect images data - id: tags - run: | - echo '::set-output name=current::vegaprotocol/${{ matrix.app }}:${{ steps.vars.outputs.tag }}' - echo '::set-output name=latest::vegaprotocol/${{ matrix.app }}:latest' - - - name: Echo tags - run: | - echo ${{ steps.tags.outputs.latest }} - echo ${{ steps.tags.outputs.current }} - - - name: Login to DockerHub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Docker build - uses: docker/build-push-action@v3 - with: - context: '.' - file: './Dockerfile.cra' - build-args: 'APP=${{ matrix.app }}' - platforms: ${{ matrix.build-platform }} - tags: ${{ steps.tags.outputs.latest }},${{ steps.tags.outputs.current }} - push: true diff --git a/.github/workflows/publish-docker-containers.yml b/.github/workflows/publish-docker-containers.yml new file mode 100644 index 000000000..6397bb4c7 --- /dev/null +++ b/.github/workflows/publish-docker-containers.yml @@ -0,0 +1,126 @@ +name: Publish docker containers + +'on': + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + - 'v[0-9]+.[0-9]+.[0-9]+-pre[0-9]+' + + workflow_dispatch: + inputs: + publish: + description: 'Publish tag to Docker Hub & GitHub Registry' + required: false + type: boolean + default: false + tag: + description: 'Git Tag to build and publish' + required: false + type: string + default: '' + apps: + description: 'Applications to build and publish' + required: false + type: choice + options: + - '["explorer", "token", "trading"]' + - '["explorer"]' + - '["token"]' + - '["trading"]' + archs: + description: 'Architecture to build and publish' + required: false + type: choice + options: + - linux/amd64, linux/arm64 + - linux/amd64 + - linux/arm64 + +jobs: + master: + strategy: + fail-fast: false + matrix: + app: ${{ fromJson(inputs.apps || '["explorer", "token", "trading"]') }} + name: Build the ${{ matrix.app }} image + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v3 + with: + ref: ${{ inputs.tag }} + + - name: Set up QEMU + id: quemu + uses: docker/setup-qemu-action@v2 + + - name: Available platforms + run: echo ${{ steps.qemu.outputs.platforms }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to DockerHub + if: ${{ inputs.publish || startsWith(github.ref, 'refs/tags/') }} + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Determine Docker Image tag + id: tags + run: | + hash=$(git rev-parse HEAD|cut -b1-8) + versionTag=${{ inputs.tag || startsWith(github.ref, 'refs/tags/') && github.ref_name || '${hash}' }} + echo ::set-output name=version::${versionTag} + echo ::set-output name=npmVersion::$(cat dockerfiles/${{ matrix.app =='trading' && 'Dockerfile.next' || 'Dockerfile.cra' }} | grep FROM | head -n 1 | awk '{print $2}' | cut -d ':' -f 2 | cut -d '-' -f 1 ) + + - name: Print config + run: | + git rev-parse --verify HEAD + git status + echo "inputs.tag=${{ inputs.tag }}" + echo "inputs.publish=${{ inputs.publish }}" + echo "inputs.apps=${{ inputs.apps }}" + echo "inputs.archs=${{ inputs.archs }}" + echo "steps.tags.outputs.version=${{ steps.tags.outputs.version }}" + + - uses: actions/setup-node@v3 + with: + node-version: ${{ steps.tags.outputs.npmVersion }} + + - name: Build frontend dists + run: | + yarn --verbose --pure-lockfile + yarn nx ${{ matrix.app =='trading' && 'export' || 'build' }} ${{ matrix.app }} --pure-lockfile + + - name: Build and export to local Docker + uses: docker/build-push-action@v3 + with: + context: . + push: false + file: dockerfiles/${{ matrix.app =='trading' && 'Dockerfile.next' || 'Dockerfile.cra' }}.dist + build-args: APP=${{ matrix.app }} + load: true + tags: vegaprotocol/${{ matrix.app }}:local + + - name: Sanity check docker image + run: | + docker run --rm vegaprotocol/${{ matrix.app }}:local cat .env + docker run --rm vegaprotocol/${{ matrix.app }}:local ls -lah + + - name: Build and push to DockerHub + id: docker_build + uses: docker/build-push-action@v3 + with: + context: . + push: ${{ inputs.publish || startsWith(github.ref, 'refs/tags/') }} + file: dockerfiles/${{ matrix.app =='trading' && 'Dockerfile.next' || 'Dockerfile.cra' }}.dist + build-args: APP=${{ matrix.app }} + platforms: ${{ inputs.archs || 'linux/amd64, linux/arm64' }} + tags: | + vegaprotocol/${{ matrix.app }}:latest + vegaprotocol/${{ matrix.app }}:${{ steps.tags.outputs.version }} + + - name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/README.md b/README.md index 723d3fe2a..5a11fd0d6 100644 --- a/README.md +++ b/README.md @@ -106,12 +106,12 @@ Visit the [Nx Documentation](https://nx.dev/getting-started/intro) to learn more ## Docker -The [Dockerfile](./Dockerfile) for running the frontends is pretty basic, merely building the application with the APP arg that is passed in and serving the application from [nginx](./nginx/nginx.conf). The only complexity that exists is that there is a script which allows the passing of run time environment variables to the containers. See configuration below for how to do this. +The [Dockerfile](./dockerfiles) for running the frontends is pretty basic, merely building the application with the APP arg that is passed in and serving the application from [nginx](./nginx/nginx.conf). The only complexity that exists is that there is a script which allows the passing of run time environment variables to the containers. See configuration below for how to do this. You can build any of the containers locally with the following command: ```bash -docker build . --build-arg APP=[YOUR APP] --tag=[TAG] +docker build --dockerfile dockerfiles/Dockerfile.cra . --build-arg APP=[YOUR APP] --tag=[TAG] ``` In order to run a container: @@ -120,6 +120,8 @@ In order to run a container: docker run -p 3000:80 [TAG] ``` +Images ending with `.dist` are to pack locally created transpiled HTML files into nginx container for non-compatible with yarn architectures like M1 Mac + ## Config As environment variables are build time and not run time in frontend applications. We have built a system which allows for passing run time environment variables, this generates a JSON file that will override the default environment variables that the container was built with (which is always testnet, using the default .env files). diff --git a/Dockerfile.cra b/dockerfiles/Dockerfile.cra similarity index 82% rename from Dockerfile.cra rename to dockerfiles/Dockerfile.cra index d2f5a237f..7025b9f85 100644 --- a/Dockerfile.cra +++ b/dockerfiles/Dockerfile.cra @@ -8,8 +8,8 @@ COPY package.json ./ COPY yarn.lock ./ COPY . ./ RUN apk add python3 make gcc g++ -RUN yarn -RUN yarn nx build $APP +RUN yarn --network-timeout 100000 --verbose --pure-lockfile +RUN yarn nx build $APP --network-timeout 100000 --verbose --pure-lockfile # Production environment FROM nginx:stable-alpine diff --git a/dockerfiles/Dockerfile.cra.dist b/dockerfiles/Dockerfile.cra.dist new file mode 100644 index 000000000..4b614c594 --- /dev/null +++ b/dockerfiles/Dockerfile.cra.dist @@ -0,0 +1,17 @@ +FROM nginx:stable-alpine +ARG APP +COPY dist/apps/$APP /usr/share/nginx/html +COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf + +EXPOSE 80 + +WORKDIR /usr/share/nginx/html +COPY ./env.sh . +COPY ./apps/$APP/.env .env + +# Add bash +RUN apk add --no-cache bash + +RUN chmod +x ./env.sh +CMD ["/bin/sh", "-c", "/usr/share/nginx/html/env.sh && nginx -g \"daemon off;\""] + diff --git a/Dockerfile.next b/dockerfiles/Dockerfile.next similarity index 82% rename from Dockerfile.next rename to dockerfiles/Dockerfile.next index b886bb99c..f3436c08b 100644 --- a/Dockerfile.next +++ b/dockerfiles/Dockerfile.next @@ -8,8 +8,8 @@ COPY package.json ./ COPY yarn.lock ./ COPY . ./ RUN apk add python3 make gcc g++ -RUN yarn -RUN yarn nx export $APP +RUN yarn --network-timeout 100000 --verbose --pure-lockfile +RUN yarn nx export $APP --network-timeout 100000 --verbose --pure-lockfile # Production environment FROM nginx:stable-alpine diff --git a/dockerfiles/Dockerfile.next.dist b/dockerfiles/Dockerfile.next.dist new file mode 100644 index 000000000..d8d0c7279 --- /dev/null +++ b/dockerfiles/Dockerfile.next.dist @@ -0,0 +1,16 @@ +FROM nginx:stable-alpine +ARG APP +COPY dist/apps/$APP/exported /usr/share/nginx/html +COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf + +EXPOSE 80 + +WORKDIR /usr/share/nginx/html +COPY ./env.sh . +COPY ./apps/$APP/.env .env + +# Add bash +RUN apk add --no-cache bash + +RUN chmod +x ./env.sh +CMD ["/bin/bash", "-c", "/usr/share/nginx/html/env.sh && nginx -g \"daemon off;\""]