Skip to content

Commit

Permalink
Merge pull request #134 from jason-fox/feature/ubi
Browse files Browse the repository at this point in the history
Amend Dockerfile to support alternative base images
  • Loading branch information
apozohue10 authored Feb 17, 2022
2 parents 63e2d52 + 50b8f47 commit 7832618
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 27 deletions.
9 changes: 5 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ name: CI
pull_request:
branches:
- master
workflow_dispatch:
jobs:
lint-dockerfile:
name: Lint Dockerfile
Expand All @@ -14,10 +15,10 @@ jobs:
- name: Git checkout
uses: actions/checkout@v2
- name: Run Hadolint Dockerfile Linter
uses: burdzwastaken/hadolint-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HADOLINT_ACTION_DOCKERFILE_FOLDER: extras/docker
uses: hadolint/hadolint-action@master
with:
dockerfile: extras/docker/Dockerfile
ignore: DL3006 DL3008 DL3018 DL3033 DL4006

lint-markdown:
name: Lint Markdown
Expand Down
6 changes: 6 additions & 0 deletions extras/docker/.hadolint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ignored:
- DL3006
- DL3008
- DL3018
- DL3033
- DL4006
64 changes: 51 additions & 13 deletions extras/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
ARG NODE_VERSION=12
ARG NODE_VERSION=14
ARG GITHUB_ACCOUNT=ging
ARG GITHUB_REPOSITORY=fiware-pep-proxy
ARG DOWNLOAD=latest
ARG SOURCE_BRANCH=master

# Default Builder, distro and distroless build version
ARG BUILDER=node:${NODE_VERSION}
ARG DISTRO=node:${NODE_VERSION}-slim
ARG DISTROLESS=gcr.io/distroless/nodejs:${NODE_VERSION}
ARG PACKAGE_MANAGER=apt
ARG USER=node

########################################################################################
#
# This build stage retrieves the source code from GitHub. The default download is the
Expand All @@ -21,26 +28,43 @@ ARG SOURCE_BRANCH=master
# --target=builder
#
########################################################################################
FROM node:${NODE_VERSION} AS builder
FROM ${BUILDER} AS builder
ARG TARGET
ARG GITHUB_ACCOUNT
ARG GITHUB_REPOSITORY
ARG DOWNLOAD
ARG SOURCE_BRANCH
ARG PACKAGE_MANAGER

SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# hadolint ignore=DL3002
USER root
# Ensure that the chosen package manger is supported by this Dockerfile
# also ensure that unzip is installed prior to downloading sources

# hadolint ignore=SC2039
RUN \
if [ "${PACKAGE_MANAGER}" = "apt" ]; then \
echo -e "\033[0;34mINFO: Using default \"${PACKAGE_MANAGER}\".\033[0m"; \
apt-get install -y --no-install-recommends unzip; \
elif [ "${PACKAGE_MANAGER}" = "yum" ]; then \
echo -e "\033[0;33mWARNING: Overriding default package manager. Using \"${PACKAGE_MANAGER}\" .\033[0m"; \
yum install -y unzip; \
yum clean all; \
elif [ "${PACKAGE_MANAGER}" = "apk" ]; then \
echo -e "\033[0;33mWARNING: Overriding default package manager. Using \"${PACKAGE_MANAGER}\" .\033[0m"; \
apk --no-cache --update-cache add gcc python3 python3-dev py-pip build-base wget curl; \
else \
echo -e "\033[0;31mERROR: Package Manager \"${PACKAGE_MANAGER}\" not supported.\033[0m"; \
exit 1; \
fi

# As an Alternative for local development, just copy this Dockerfile into file the root of
# the repository and replace the whole RUN statement below by the following COPY statement
# in your local source using :
#
# COPY . ${TARGET}/
#

# hadolint ignore=DL3008
RUN \
# Ensure that unzip is installed prior to downloading
apt-get install -y --no-install-recommends unzip && \
if [ "${DOWNLOAD}" = "latest" ] ; \
then \
RELEASE="${SOURCE_BRANCH}"; \
Expand All @@ -55,7 +79,7 @@ RUN \
fi && \
RELEASE_CONCAT=$(echo "${RELEASE}" | tr / -); \
curl -s -L https://github.com/"${GITHUB_ACCOUNT}"/"${GITHUB_REPOSITORY}"/archive/"${RELEASE}".zip > source.zip && \
unzip source.zip -x "*/test/**" "*/sanity/**" "*/extras/**" "*/doc/**" "*/.*" && \
unzip source.zip -x "*/.github/**" "*/test/**" "*/sanity/**" "*/extras/**" "*/signatures/**" "*/doc/**" "*/.*" && \
rm source.zip && \
mv "${GITHUB_REPOSITORY}-${RELEASE_CONCAT}" /opt/fiware-pep-proxy

Expand All @@ -64,15 +88,17 @@ WORKDIR /opt/fiware-pep-proxy
# hadolint ignore=DL3008
RUN \
echo "INFO: npm install --production..." && \
npm install --only=prod --no-package-lock --no-optional
npm install --only=prod --no-package-lock --no-optional --unsafe-perm

########################################################################################
#
# This build stage creates an anonymous user to be used with the distroless build
# as defined below.
#
########################################################################################
FROM node:${NODE_VERSION} AS anon-user
FROM ${BUILDER} AS anon-user
# hadolint ignore=DL3002
USER root
RUN sed -i -r "/^(root|nobody)/!d" /etc/passwd /etc/shadow /etc/group \
&& sed -i -r 's#^(.*):[^:]*$#\1:/sbin/nologin#' /etc/passwd

Expand All @@ -90,12 +116,16 @@ RUN sed -i -r "/^(root|nobody)/!d" /etc/passwd /etc/shadow /etc/group \
#
########################################################################################

FROM gcr.io/distroless/nodejs:${NODE_VERSION} AS distroless
FROM ${DISTROLESS} AS distroless
ARG GITHUB_ACCOUNT
ARG GITHUB_REPOSITORY
ARG NODE_VERSION

LABEL "maintainer"="FIWARE Identity Manager Team. DIT-UPM"
LABEL "description"="Support for proxy functions within OAuth2-based authentication schemas. Also implements PEP functions within an XACML-based access control schema."
LABEL "name"="pep-proxy"
LABEL "summary"="PEP Proxy - Wilma (Distroless)"

LABEL "org.opencontainers.image.authors"=""
LABEL "org.opencontainers.image.documentation"="https://fiware-idm.readthedocs.io/"
LABEL "org.opencontainers.image.vendor"="Universidad Politécnica de Madrid."
Expand Down Expand Up @@ -132,12 +162,18 @@ HEALTHCHECK --interval=30s --timeout=3s --start-period=60s \
#
########################################################################################

FROM node:${NODE_VERSION}-slim AS slim
FROM ${DISTRO} AS slim
ARG GITHUB_ACCOUNT
ARG GITHUB_REPOSITORY
ARG NODE_VERSION
ARG USER


LABEL "maintainer"="FIWARE Identity Manager Team. DIT-UPM"
LABEL "description"="Support for proxy functions within OAuth2-based authentication schemas. Also implements PEP functions within an XACML-based access control schema."
LABEL "name"="pep-proxy"
LABEL "summary"="PEP Proxy - Wilma"

LABEL "org.opencontainers.image.authors"=""
LABEL "org.opencontainers.image.documentation"="https://fiware-idm.readthedocs.io/"
LABEL "org.opencontainers.image.vendor"="Universidad Politécnica de Madrid."
Expand All @@ -148,9 +184,11 @@ LABEL "org.opencontainers.image.source"=https://github.com/${GITHUB_ACCOUNT}/${G
LABEL "org.nodejs.version"=${NODE_VERSION}

COPY --from=builder /opt/fiware-pep-proxy /opt/fiware-pep-proxy
COPY --from=builder /opt/fiware-pep-proxy/LICENSE /licenses/LICENSE
WORKDIR /opt/fiware-pep-proxy

USER node
# Node by default, use 406 for Alpine, 1001 for UBI,
USER ${USER}
ENV NODE_ENV=production
# Ports used by application
EXPOSE ${PEP_PROXY_PORT:-1027}
Expand Down
69 changes: 59 additions & 10 deletions extras/docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,26 +32,30 @@ sudo docker images
Now you can run a new container from the image you have just created with:

```console
sudo docker run -d --name pep-proxy-container -v [host_config_file]:/opt/fiware-pep-proxy/config.js -p [host_port]:[container_port] pep-proxy-image
sudo docker run -d --name pep-proxy-container \
-v [host_config_file]:/opt/fiware-pep-proxy/config.js \
-p [host_port]:[container_port] pep-proxy-image
```

Where the different params mean:

- -d indicates that the container runs as a daemon
- --name is the name of the new container (you can use the name you want)
- -v stablishes a relation between a local folder (in your host computer) and a container's folder. In this case it is
used to pass to the container the configuration file that PEP Proxy needs to work. `host_config_file` has to be the
location of a local file with that configuration following the
- `-d` indicates that the container runs as a daemon
- `--name` is the name of the new container (you can use the name you want)
- `-v` stablishes a relation between a local folder (in your host computer) and a container's folder. In this case it
is used to pass to the container the configuration file that PEP Proxy needs to work. `host_config_file` has to be
the location of a local file with that configuration following the
[config template](https://github.com/ging/fiware-pep-proxy/blob/master/config.js.template).
- -p stablishes a relation between a local port and a container's port. You can use the port you want in `host_port`
- `-p` stablishes a relation between a local port and a container's port. You can use the port you want in `host_port`
but `container_port` has to be the same that you have set in `config.app_port` in your config file. If you have set
`config.https` to `true` you have to use here the HTTPS port.
- the last param is the name of the image
- the final param is the name of the image

Here is an example of this command:

```console
sudo docker run -d --name pep-proxy -v /home/root/workspace/fiware-pep-proxy/config.js:/opt/fiware-pep-proxy/config.js -p 80:80 pep-proxy-image
sudo docker run -d --name pep-proxy \
-v /home/root/workspace/fiware-pep-proxy/config.js:/opt/fiware-pep-proxy/config.js \
-p 80:80 pep-proxy-image
```

Once the container is running you can view the console logs using:
Expand All @@ -73,11 +77,56 @@ this case you have only to execute the run command. But now the image name is fi
is the release you want to use:

```console
sudo docker run -d --name pep-proxy-container -v [host_config_file]:/opt/fiware-pep-proxy/config.js -p [host_port]:[container_port] fiware/pep-proxy
sudo docker run -d --name pep-proxy-container \
-v [host_config_file]:/opt/fiware-pep-proxy/config.js \
-p [host_port]:[container_port] fiware/pep-proxy
```

> **Note** If you do not specify a version you are pulling from `latest` by default.
## Building using an alternative sources and Linux Distros

The `Dockerfile` is flexible enough to be able to use
[alternative base images](https://kuberty.io/blog/best-os-for-docker/) should you wish. The base image defaults to using
the `node:slim` distro, but other base images can be injected using `--build-arg` parameters on the commmand line. For
example, to create a container based on
[Red Hat UBI (Universal Base Image) 8](https://developers.redhat.com/articles/2021/11/08/optimize-nodejs-images-ubi-8-nodejs-minimal-image)
add `BUILDER`, `DISTRO`, `PACKAGE_MANAGER` and `USER` parameters as shown:

```console
sudo docker build -t pep-proxy \
--build-arg BUILDER=registry.access.redhat.com/ubi8/nodejs-14 \
--build-arg DISTRO=registry.access.redhat.com/ubi8/nodejs-14-minimal \
--build-arg PACKAGE_MANAGER=yum \
--build-arg USER=1001 . --no-cache
```

To create a container based on [Alpine Linux](https://alpinelinux.org/about/) add `BUILDER`, `DISTRO`, `PACKAGE_MANAGER`
and `USER` parameters as shown:

```console
docker build -t pep-proxy \
--build-arg BUILDER=node:16-alpine \
--build-arg DISTRO=node:16-alpine \
--build-arg PACKAGE_MANAGER=apk . \
--build-arg USER=406 . --no-cache
```

Currently, the following `--build-arg` parameters are supported:

| Parameter | Description |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `BUILDER` | Preferred [linux distro](https://kuberty.io/blog/best-os-for-docker/) to use whilst building the image, defaults to `node:${NODE_VERSION}` |
| `DISTRO` | Preferred [linux distro](https://kuberty.io/blog/best-os-for-docker/) to use for the final container image, defaults to `node:${NODE_VERSION}-slim` |
| `DISTROLESS` | Preferred [Distroless Image](https://betterprogramming.pub/how-to-harden-your-containers-with-distroless-docker-images-c2abd7c71fdb) to use for the final container. Distroless images can be built using `-target=distroless` , defaults to `gcr.io/distroless/nodejs:${NODE_VERSION}` |
| `DOWNLOAD` | The GitHub SHA or tag to download - defaults to `latest` |
| `GITHUB_ACCOUNT` | The GitHub Action to download the source files from, defaults to `ging` |
| `GITHUB_REPOSITORY` | The name of the GitHub repository to download the source files from, defaults to `fiware-pep-proxy` |
| `NODE_VERSION` | the version of Node.js to use |
| `PACKAGE_MANAGER` | Package manager to use whilst creating the build, defaults to `apt` |
| `SOURCE_BRANCH` | The GitHub repository branch to download the source files from, defaults to `master` |
| `USER` | User in the final container image, defaults to `node` |

### Docker Environment Variables

- `PEP_PROXY_PORT` - default value is `80`
Expand Down

0 comments on commit 7832618

Please sign in to comment.