Skip to content

Commit

Permalink
Merge pull request #1535 from ral-facilities/k8s-deployment
Browse files Browse the repository at this point in the history
Containerize application and configure GitHub Actions to build and push Docker image to Harbor
  • Loading branch information
VKTB authored Dec 5, 2023
2 parents 1923737 + f9c87e0 commit f31e6dc
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 1 deletion.
17 changes: 17 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/.github
/.husky
/packages/datagateway-*/cypress
/packages/datagateway-*/cypress.json
/packages/datagateway-*/server
/packages/datagateway-*/README.md
**/build
**/coverage
**/lib
**/node_modules
.gitignore
.prettierrc
codecov.yml
CODEOWNERS
LICENSE.md
README.md
Dockerfile
33 changes: 32 additions & 1 deletion .github/workflows/ci-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: CI Build
on:
workflow_dispatch:
pull_request:
# By default, the pull_request event type is not triggered when a PR is merged into main
# By default, the pull_request event type is not triggered when a PR is merged into main or develop
push:
branches:
- main
Expand Down Expand Up @@ -457,3 +457,34 @@ jobs:
with:
name: Search-Screenshots
path: packages/datagateway-search/cypress/screenshots

docker:
# This job triggers only if all the other jobs succeed. It builds the Docker image and if successful,
# it pushes it to Harbor.
needs: [lint-and-unit-test, dataview-e2e-tests, download-e2e-tests, search-e2e-tests]
name: Docker
runs-on: ubuntu-20.04
steps:
- name: Checkout repo
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3

- name: Login to Harbor
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0
with:
registry: harbor.stfc.ac.uk/datagateway
username: ${{ secrets.HARBOR_USERNAME }}
password: ${{ secrets.HARBOR_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@c4ee3adeed93b1fa6a762f209fb01608c1a22f1e # v4.4.0
with:
images: harbor.stfc.ac.uk/datagateway/plugins

- name: Build and push Docker image to Harbor
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 # v4.0.0
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
75 changes: 75 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Dockerfile to build and serve datagateway

# Build stage
FROM node:20.9-alpine3.18 as builder

WORKDIR /datagateway-build

# Enable dependency caching and share the cache between projects
ENV YARN_ENABLE_GLOBAL_CACHE=true
ENV YARN_GLOBAL_FOLDER=/root/.cache/.yarn

COPY . .

RUN --mount=type=cache,target=/root/.cache/.yarn/cache \
set -eux; \
# Set the React production variables which hold reference to the paths of the plugin builds \
echo "REACT_APP_DATAVIEW_BUILD_DIRECTORY=/datagateway-dataview/" > packages/datagateway-dataview/.env.production; \
echo "REACT_APP_DOWNLOAD_BUILD_DIRECTORY=/datagateway-download/" > packages/datagateway-download/.env.production; \
echo "REACT_APP_SEARCH_BUILD_DIRECTORY=/datagateway-search/" > packages/datagateway-search/.env.production; \
\
cp packages/datagateway-dataview/public/datagateway-dataview-settings.example.json packages/datagateway-dataview/public/datagateway-dataview-settings.json; \
cp packages/datagateway-download/public/datagateway-download-settings.example.json packages/datagateway-download/public/datagateway-download-settings.json; \
cp packages/datagateway-search/public/datagateway-search-settings.example.json packages/datagateway-search/public/datagateway-search-settings.json; \
\
yarn workspaces focus --all --production; \
yarn build;

# Run stage
FROM httpd:2.4-alpine3.15

WORKDIR /usr/local/apache2/htdocs

# Put the output of the build into an apache server
COPY --from=builder /datagateway-build/packages/datagateway-dataview/build/. ./datagateway-dataview/
COPY --from=builder /datagateway-build/packages/datagateway-download/build/. ./datagateway-download/
COPY --from=builder /datagateway-build/packages/datagateway-search/build/. ./datagateway-search/

RUN set -eux; \
\
# Enable mod_deflate \
sed -i -e 's/^#LoadModule deflate_module/LoadModule deflate_module/' /usr/local/apache2/conf/httpd.conf; \
# Compress all files except images \
echo 'SetOutputFilter DEFLATE' >> /usr/local/apache2/conf/httpd.conf; \
echo 'SetEnvIfNoCase Request_URI "\.(?:gif|jpe?g|png)$" no-gzip' >> /usr/local/apache2/conf/httpd.conf; \
# Disable caching for .js, .json, and .html files \
echo '<FilesMatch ".(js|json|html)$">' >> /usr/local/apache2/conf/httpd.conf; \
echo ' Header set Cache-Control "no-cache"' >> /usr/local/apache2/conf/httpd.conf; \
echo '</FilesMatch>' >> /usr/local/apache2/conf/httpd.conf; \
\
# Privileged ports are permitted to root only by default. \
# setcap to bind to privileged ports (80) as non-root. \
apk --no-cache add libcap; \
setcap 'cap_net_bind_service=+ep' /usr/local/apache2/bin/httpd; \
\
# Change ownership of logs directory \
chown www-data:www-data /usr/local/apache2/logs; \
\
# Change ownership of setting files \
chown www-data:www-data /usr/local/apache2/htdocs/datagateway-dataview/datagateway-dataview-settings.json; \
chown www-data:www-data /usr/local/apache2/htdocs/datagateway-download/datagateway-download-settings.json; \
chown www-data:www-data /usr/local/apache2/htdocs/datagateway-search/datagateway-search-settings.json;

# Switch to non-root user defined in httpd image
USER www-data

ENV API_URL="/datagateway-api"
ENV DOWNLOAD_API_URL="http://localhost"
ENV ICAT_URL="http://localhost"
ENV IDS_URL="http://localhost"

COPY docker/docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]

CMD ["httpd-foreground"]
EXPOSE 80
34 changes: 34 additions & 0 deletions docker/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/sh -eu

# Use a tempfile instead of sed -i so that only the file, not the directory needs to be writable
TEMPFILE="$(mktemp)"

# Set values in datagateway-dataview-settings.json from environment variables
sed -e "s|\"idsUrl\": \".*\"|\"idsUrl\": \"$IDS_URL\"|" \
-e "s|\"apiUrl\": \".*\"|\"apiUrl\": \"$API_URL\"|" \
-e "s|\"downloadApiUrl\": \".*\"|\"downloadApiUrl\": \"$DOWNLOAD_API_URL\"|" \
/usr/local/apache2/htdocs/datagateway-dataview/datagateway-dataview-settings.json > "$TEMPFILE"

cat "$TEMPFILE" > /usr/local/apache2/htdocs/datagateway-dataview/datagateway-dataview-settings.json

# Set values in datagateway-download-settings.json from environment variables
sed -e "s|\"idsUrl\": \".*\"|\"idsUrl\": \"$IDS_URL\"|" \
-e "s|\"apiUrl\": \".*\"|\"apiUrl\": \"$API_URL\"|" \
-e "s|\"downloadApiUrl\": \".*\"|\"downloadApiUrl\": \"$DOWNLOAD_API_URL\"|" \
/usr/local/apache2/htdocs/datagateway-download/datagateway-download-settings.json > "$TEMPFILE"

cat "$TEMPFILE" > /usr/local/apache2/htdocs/datagateway-download/datagateway-download-settings.json

# Set values in datagateway-search-settings.json from environment variables
sed -e "s|\"idsUrl\": \".*\"|\"idsUrl\": \"$IDS_URL\"|" \
-e "s|\"apiUrl\": \".*\"|\"apiUrl\": \"$API_URL\"|" \
-e "s|\"downloadApiUrl\": \".*\"|\"downloadApiUrl\": \"$DOWNLOAD_API_URL\"|" \
-e "s|\"icatUrl\": \".*\"|\"icatUrl\": \"$ICAT_URL\"|" \
/usr/local/apache2/htdocs/datagateway-search/datagateway-search-settings.json > "$TEMPFILE"

cat "$TEMPFILE" > /usr/local/apache2/htdocs/datagateway-search/datagateway-search-settings.json

rm "$TEMPFILE"

# Run the CMD instruction
exec "$@"

0 comments on commit f31e6dc

Please sign in to comment.