From 18d5e73e1384c16fbc186075d8d616816301351f Mon Sep 17 00:00:00 2001 From: Slava <20563034+veaceslavdoina@users.noreply.github.com> Date: Fri, 1 Dec 2023 10:24:51 +0200 Subject: [PATCH] Configure automated Docker builds (#11) * Configure automated Docker builds (#10) * Fix Nginx template loading (#10) --- .github/workflows/docker-reusable.yml | 177 ++++++++++++++++++ .github/workflows/docker.yml | 26 +++ Dockerfile.client | 16 -- README.md | 37 ++-- build-docker.bat | 2 - deployment/nginx.template | 21 --- docker-compose.yml | 6 +- docker/Dockerfile | 32 ++++ docker/build-docker.bat | 9 + docker/nginx.template | 30 +++ .../src/pages/data/tabs/upload/UploadTab.tsx | 2 +- 11 files changed, 300 insertions(+), 58 deletions(-) create mode 100644 .github/workflows/docker-reusable.yml create mode 100644 .github/workflows/docker.yml delete mode 100644 Dockerfile.client delete mode 100644 build-docker.bat delete mode 100644 deployment/nginx.template create mode 100644 docker/Dockerfile create mode 100644 docker/build-docker.bat create mode 100644 docker/nginx.template diff --git a/.github/workflows/docker-reusable.yml b/.github/workflows/docker-reusable.yml new file mode 100644 index 0000000..87754b0 --- /dev/null +++ b/.github/workflows/docker-reusable.yml @@ -0,0 +1,177 @@ +name: Docker - Reusable + + +on: + workflow_call: + inputs: + docker_file: + default: docker/Dockerfile + description: Dockerfile + required: false + type: string + docker_repo: + default: codexstorage/codex-frontend + description: DockerHub repository + required: false + type: string + tag_latest: + default: true + description: Set latest tag for Docker images + required: false + type: boolean + tag_sha: + default: true + description: Set Git short commit as Docker tag + required: false + type: boolean + tag_suffix: + default: '' + description: Suffix for Docker images tag + required: false + type: string + + +env: + DOCKER_FILE: ${{ inputs.docker_file }} + DOCKER_REPO: ${{ inputs.docker_repo }} + TAG_LATEST: ${{ inputs.tag_latest }} + TAG_SHA: ${{ inputs.tag_sha }} + TAG_SUFFIX: ${{ inputs.tag_suffix }} + + +jobs: + # 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 }} + env: + PLATFORM: ${{ 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 }} + + - name: Docker - Set up Buildx + uses: docker/setup-buildx-action@v2 + + - name: Docker - Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Docker - Build and Push by digest + id: build + uses: docker/build-push-action@v4 + with: + context: . + file: ${{ env.DOCKER_FILE }} + platforms: ${{ env.PLATFORM }} + push: true + labels: ${{ steps.meta.outputs.labels }} + outputs: type=image,name=${{ env.DOCKER_REPO }},push-by-digest=true,name-canonical=true,push=true + + - name: Docker - Export digest + run: | + mkdir -p /tmp/digests + digest="${{ steps.build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" + + - name: Docker - Upload digest + uses: actions/upload-artifact@v3 + with: + name: digests + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + + # Publish multi-platform image + publish: + name: Publish multi-platform image + runs-on: ubuntu-latest + needs: build + steps: + - name: Docker - Variables + run: | + # Adjust custom suffix when set and + if [[ -n "${{ env.TAG_SUFFIX }}" ]]; then + echo "TAG_SUFFIX=-${{ env.TAG_SUFFIX }}" >>$GITHUB_ENV + fi + # Disable SHA tags on tagged release + if [[ ${{ startsWith(github.ref, 'refs/tags/') }} == "true" ]]; then + echo "TAG_SHA=false" >>$GITHUB_ENV + fi + # Handle latest and latest-custom using raw + if [[ ${{ env.TAG_SHA }} == "false" ]]; then + echo "TAG_LATEST=false" >>$GITHUB_ENV + echo "TAG_RAW=true" >>$GITHUB_ENV + if [[ -z "${{ env.TAG_SUFFIX }}" ]]; then + echo "TAG_RAW_VALUE=latest" >>$GITHUB_ENV + else + echo "TAG_RAW_VALUE=latest-{{ env.TAG_SUFFIX }}" >>$GITHUB_ENV + fi + else + echo "TAG_RAW=false" >>$GITHUB_ENV + fi + + - name: Docker - Download digests + uses: actions/download-artifact@v3 + with: + name: digests + path: /tmp/digests + + - name: Docker - Set up Buildx + uses: docker/setup-buildx-action@v2 + + - name: Docker - Meta + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.DOCKER_REPO }} + flavor: | + latest=${{ env.TAG_LATEST }} + suffix=${{ env.TAG_SUFFIX }},onlatest=true + tags: | + type=semver,pattern={{version}} + type=raw,enable=${{ env.TAG_RAW }},value=latest + type=sha,enable=${{ env.TAG_SHA }} + + - name: Docker - Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Docker - Create manifest list and push + working-directory: /tmp/digests + run: | + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.DOCKER_REPO }}@sha256:%s ' *) + + - name: Docker - Inspect image + run: | + docker buildx imagetools inspect ${{ env.DOCKER_REPO }}:${{ steps.meta.outputs.version }} diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..33dd6e4 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,26 @@ +name: Docker + + +on: + push: + branches: + - master + tags: + - 'v*.*.*' + paths-ignore: + - '**/*.md' + - '**/.gitignore' + - 'docker/**' + - '!docker/Dockerfile' + - '!docker/nginx.template' + - '.github/**' + - '!.github/workflows/docker.yml' + - '!.github/workflows/docker-reusable.yml' + workflow_dispatch: + + +jobs: + build-and-push: + name: Build and Push + uses: ./.github/workflows/docker-reusable.yml + secrets: inherit diff --git a/Dockerfile.client b/Dockerfile.client deleted file mode 100644 index cc5466a..0000000 --- a/Dockerfile.client +++ /dev/null @@ -1,16 +0,0 @@ -# Build step #1: build the React front end -FROM node:18 as build-step -WORKDIR /frontend -ENV PATH /frontend/node_modules/.bin:$PATH -COPY frontend/package.json frontend/yarn.lock frontend/tsconfig.json ./ -COPY frontend/src ./src -COPY frontend/public ./public -RUN yarn install -RUN yarn build --production - -# Build step #2: build an nginx container -FROM nginx:stable-alpine -COPY --from=build-step /frontend/build /usr/share/nginx/html -COPY deployment/nginx.template /etc/nginx/nginx.template - -CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/README.md b/README.md index 9637265..401a9fd 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ A frontend for codex made with Flutter. + ## Features - Upload multiple files at once @@ -12,28 +13,36 @@ A frontend for codex made with Flutter. - Download from codex nodes - Now supports marketplace endpoints! + ## Planned Features - Show status of connection to codex peers - Settings for the connection - -## How To Run It -```console -git clone https://github.com/Kayvon-Martinez/codex-frontend -cd codex-frontend -``` -Grab your codex api link and put it in the dockercompose file in the root of the directory in the value of codex_url +## How to run it -```console -docker compose up -``` + 1. Clone repository + ```shell + git clone https://github.com/codex-storage/codex-frontend + cd codex-frontend + ``` + + 2. Grab your codex api link and define a variable for docker compose file + ```shell + export codex_url="http://localhost:8080" + ``` + + 3. Run codex frontend + ```shell + docker compose up + ``` + + 4. Go to [localhost:3000](http://localhost:3000) -Go to [localhost:3000](http://localhost:3000) ## Screenshots -![Data page: Upload](https://github.com/Kayvon-Martinez/codex-frontend/blob/master/screenshots/upload-page.png) -![Data page: Upload (with uploads)](https://github.com/Kayvon-Martinez/codex-frontend/blob/master/screenshots/upload-page-uploads.png) -![Data page: Download](https://github.com/Kayvon-Martinez/codex-frontend/blob/master/screenshots/download-page.png) +![Data page: Upload](screenshots/upload-page.png) +![Data page: Upload (with uploads)](screenshots/upload-page-uploads.png) +![Data page: Download](screenshots/download-page.png) diff --git a/build-docker.bat b/build-docker.bat deleted file mode 100644 index c78abcd..0000000 --- a/build-docker.bat +++ /dev/null @@ -1,2 +0,0 @@ -docker build -f Dockerfile.client -t thatbenbierens/codex-frontend:initial . -docker push thatbenbierens/codex-frontend:initial diff --git a/deployment/nginx.template b/deployment/nginx.template deleted file mode 100644 index 85aaca7..0000000 --- a/deployment/nginx.template +++ /dev/null @@ -1,21 +0,0 @@ -server -{ - listen 80; - server_name localhost; - - root /usr/share/nginx/html; - index index.html; - error_page 500 502 503 504 /50x.html; - - location /api { - proxy_pass $codex_url; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - location / { - try_files $uri /index.html; - add_header Cache-Control "no-cache"; - } -} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 1a9c402..95dc8ee 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,11 +3,9 @@ services: client: build: context: . - dockerfile: Dockerfile.client + dockerfile: docker/Dockerfile image: codex-frontend-client ports: - "3000:80" environment: - - codex_url=http://kubernetes.docker.internal:31264 - volumes: - - ./deployment/nginx.template:/etc/nginx/templates/10-variables.conf.template:ro \ No newline at end of file + - codex_url=${codex_url:-http://kubernetes.docker.internal:31264} diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..ec22d8e --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,32 @@ +# Variables +ARG BUILDER=node:18 +ARG IMAGE=nginx:stable-alpine +ARG APP_USER=root +ARG APP_SRC=frontend +ARG APP_HOME=/frontend +ARG NGINX_TEMPLATE=docker/nginx.template + +# Build +FROM ${BUILDER} AS builder + +ARG APP_USER +ARG APP_SRC +ARG APP_HOME + +WORKDIR ${APP_HOME} +COPY --chown=${APP_USER}:${APP_USER} ${APP_SRC} . + +RUN yarn install +RUN yarn build --production + + +# Create +FROM ${IMAGE} + +ARG APP_USER +ARG APP_HOME +ARG NGINX_TEMPLATE + +RUN mkdir /etc/nginx/templates +COPY ${NGINX_TEMPLATE} /etc/nginx/templates/default.conf.template +COPY --chown=${APP_USER}:${APP_USER} --from=builder ${APP_HOME}/build /usr/share/nginx/html diff --git a/docker/build-docker.bat b/docker/build-docker.bat new file mode 100644 index 0000000..cfecdf8 --- /dev/null +++ b/docker/build-docker.bat @@ -0,0 +1,9 @@ +:: Variables +set REPOSITORY=thatbenbierens/codex-frontend +set TAG=initial +set APP_SRC=../frontend +set NGINX_TEMPLATE=docker/nginx.template + +:: Build +docker build --build-arg APP_SRC=%APP_SRC% --build-arg NGINX_TEMPLATE=%NGINX_TEMPLATE% -t %REPOSITORY%:%TAG% . +docker push %REPOSITORY%:%TAG% diff --git a/docker/nginx.template b/docker/nginx.template new file mode 100644 index 0000000..ac79fa5 --- /dev/null +++ b/docker/nginx.template @@ -0,0 +1,30 @@ +log_format custom + '$remote_addr - $request_time - [$time_local] - $msec - ' + '$request_id - $connection-$connection_requests - ' + '$scheme - $host - $server_port - ' + '$request_method - $request_uri - $server_protocol - $status - $request_completion - ' + '$bytes_sent - $request_length - "$http_referer" - "$http_user_agent" - ' + '$proxy_host - "$upstream_addr" - "$upstream_status" - "$upstream_connect_time" - "$upstream_response_time" '; + +server { + listen 80; + server_name localhost; + + root /usr/share/nginx/html; + index index.html; + error_page 500 502 503 504 /50x.html; + access_log /var/log/nginx/access.log custom; + + location / { + try_files $uri /index.html; + add_header Cache-Control "no-cache"; + } + + location /api { + proxy_pass $codex_url; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} diff --git a/frontend/src/pages/data/tabs/upload/UploadTab.tsx b/frontend/src/pages/data/tabs/upload/UploadTab.tsx index 44ba889..5da8abf 100644 --- a/frontend/src/pages/data/tabs/upload/UploadTab.tsx +++ b/frontend/src/pages/data/tabs/upload/UploadTab.tsx @@ -4,7 +4,7 @@ import styled from "styled-components"; import UploadedItemModel, { UploadedItemStatus, } from "../../../../data/models/UploadedItemModel"; -import UploadedItemComponent from "../../../../components/UploadedItem/UploadedItemComponent"; +import UploadedItemComponent from "../../../../components/uploadedItem/UploadedItemComponent"; import axios from "axios"; import { useDexyStore } from "../../../../store";