diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 0000000..bb127ea --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,50 @@ +name: Build and Push Docker Images + +on: [push] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=sha,format=long + type=semver,pattern={{version}} + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..676490f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,52 @@ +# Stage 1: build node assets +FROM node:22 AS node-build +WORKDIR /app + +# Install packages first; need to install here to be cached in earlier layer +# and not trigger re-compiles if only source code changes +COPY package.json package-lock.json /app +RUN npm ci + +# Copy the source code into the container +COPY \ + .browserslistrc \ + .nvmrc \ + .editorconfig \ + jsconfig.json \ + vite.config.mjs \ + index.html \ + /app/ + +COPY public /app/public +COPY src /app/src + +# Run build +ENV NODE_ENV=production +RUN npm run build +RUN find /app/dist -type f -print0 | xargs -0 chmod 644 +RUN find /app/dist -type d -print0 | xargs -0 chmod 755 + +# Stage 2: nginx +# This copies built assets from previous stage +# nginxinc/nginx-unprivileged is a docker image that allows running nginx w/o root +FROM nginxinc/nginx-unprivileged:mainline-bookworm +COPY --from=node-build /app/dist /usr/share/nginx/html/ + +LABEL org.label-schema.name="colocus-ui" +LABEL org.label-schema.description="Vue frontend for Colocus browser" +LABEL org.label-schema.vendor="University of Michigan, Center for Statistical Genetics" +LABEL org.label-schema.url="https://github.com/statgen/colocus-ui-vue3" +LABEL org.label-schema.usage="https://github.com/statgen/colocus-ui-vue3#docker" +LABEL org.label-schema.vcs-url="https://github.com/statgen/colocus-ui-vue3" +LABEL org.label-schema.schema-version="1.0" + +ARG BUILD_DATE +ARG GIT_SHA +ARG COLOCUS_UI_VERSION + +LABEL org.label-schema.version=$COLOCUS_UI_VERSION \ + org.label-schema.vcs-ref=$GIT_SHA \ + org.label-schema.build-date=$BUILD_DATE + +# Start NGINX in the foreground +CMD ["nginx", "-g", "daemon off;"] diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 0000000..c795d47 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,38 @@ +FROM node:22 AS node-build +WORKDIR /app + +# Install packages first; need to install here to be cached in earlier layer +# and not trigger re-compiles if only source code changes +COPY package.json package-lock.json /app/ +RUN npm ci + +# Copy the source code into the container +COPY \ + .browserslistrc \ + .nvmrc \ + .editorconfig \ + jsconfig.json \ + vite.config.mjs \ + index.html \ + /app/ + +COPY public /app/public +COPY src /app/src + +LABEL org.label-schema.name="colocus-ui" +LABEL org.label-schema.description="Development image for Colocus UI" +LABEL org.label-schema.vendor="University of Michigan, Center for Statistical Genetics" +LABEL org.label-schema.url="https://github.com/statgen/colocus-ui-vue3" +LABEL org.label-schema.usage="https://github.com/statgen/colocus-ui-vue3#docker" +LABEL org.label-schema.vcs-url="https://github.com/statgen/colocus-ui-vue3" +LABEL org.label-schema.schema-version="1.0" + +ARG BUILD_DATE +ARG GIT_SHA +ARG COLOCUS_UI_VERSION + +LABEL org.label-schema.version=$COLOCUS_UI_VERSION \ + org.label-schema.vcs-ref=$GIT_SHA \ + org.label-schema.build-date=$BUILD_DATE + +CMD ["sh", "-c", "node --no-warnings ./node_modules/.bin/vite --host 0.0.0.0 --port ${VITE_PORT:-5173} --strictPort"] diff --git a/bin/docker-build.sh b/bin/docker-build.sh new file mode 100755 index 0000000..70fe782 --- /dev/null +++ b/bin/docker-build.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -euxo pipefail + +COLOCUS_UI_VERSION=`git describe --tags --abbrev=11 | sed 's/^v//' | sed 's/-g/-/'` +GIT_SHA=`git rev-parse HEAD` +BUILD_DATE=`date -u +'%Y-%m-%dT%H:%M:%SZ'` + +docker build --pull -t colocus-ui:${COLOCUS_UI_VERSION} \ + --build-arg BUILD_DATE=${BUILD_DATE} \ + --build-arg GIT_SHA=${GIT_SHA} \ + --build-arg COLOCUS_UI_VERSION=${COLOCUS_UI_VERSION} \ + --progress plain \ + "$@" . + +docker tag colocus-ui:${COLOCUS_UI_VERSION} colocus-ui:latest diff --git a/vite.config.mjs b/vite.config.mjs index 86e2dab..1f2de27 100644 --- a/vite.config.mjs +++ b/vite.config.mjs @@ -107,7 +107,7 @@ export default defineConfig({ server: { proxy: { '/api/': { - target: 'http://127.0.0.1:8000', + target: process.env.VITE_API_URL || 'http://127.0.0.1:8000', changeOrigin: true, }, },