From 6eecced596933eb38dff5720360fc52d351b22d2 Mon Sep 17 00:00:00 2001 From: Ashhad Ali Date: Mon, 19 Oct 2026 18:07:29 +0500 Subject: [PATCH 1/5] feat: harden container with non-root execution and smoke tests --- Dockerfile | 70 ++++++++++++++++++++++--------------- entrypoint.sh | 22 +++--------- tests/smoke-test-nonroot.sh | 52 +++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 46 deletions(-) create mode 100755 tests/smoke-test-nonroot.sh diff --git a/Dockerfile b/Dockerfile index ce337f6..4576e13 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,20 +1,34 @@ FROM python:3.12-slim -# Pinned tool versions. Unpinned installs make the image non-reproducible and -# let an upstream release change scan results without a DockSec change. ARG TRIVY_VERSION=0.74.0 ARG HADOLINT_VERSION=2.15.1 +ARG DOCKER_CLI_VERSION=27.3.1 +ARG DOCKER_GID=999 +ARG DOCKER_UID=10001 +ARG DOCKER_USER_GID=10001 -# Install system dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ - curl \ - git \ + curl \ + git \ + ca-certificates \ + gosu \ && rm -rf /var/lib/apt/lists/* -# Install Hadolint. -# -f is required: without it curl exits 0 on an HTTP error and writes the error -# page to the destination, producing a "successful" build with a text file where -# the binary should be. +RUN set -eux; \ + arch="$(dpkg --print-architecture)"; \ + case "$arch" in \ + amd64) docker_arch='x86_64' ;; \ + arm64) docker_arch='aarch64' ;; \ + *) echo "unsupported architecture: $arch" >&2; exit 1 ;; \ + esac; \ + curl -fsSL -o /tmp/docker.tgz \ + "https://download.docker.com/linux/static/stable/${docker_arch}/docker-${DOCKER_CLI_VERSION}.tgz"; \ + tar -xzf /tmp/docker.tgz -C /tmp; \ + mv /tmp/docker/docker /usr/local/bin/docker; \ + chmod +x /usr/local/bin/docker; \ + rm -rf /tmp/docker /tmp/docker.tgz; \ + docker --version + RUN set -eux; \ arch="$(dpkg --print-architecture)"; \ case "$arch" in \ @@ -26,9 +40,6 @@ RUN set -eux; \ "https://github.com/hadolint/hadolint/releases/download/v${HADOLINT_VERSION}/hadolint-Linux-${hadolint_arch}"; \ chmod +x /usr/local/bin/hadolint -# Install Trivy from the release tarball rather than the install script, so the -# download is version-addressed and a redirect or a moved script cannot silently -# change what lands in the image. RUN set -eux; \ arch="$(dpkg --print-architecture)"; \ case "$arch" in \ @@ -41,32 +52,33 @@ RUN set -eux; \ tar -xzf /tmp/trivy.tar.gz -C /usr/local/bin trivy; \ rm -f /tmp/trivy.tar.gz -# Fail the build if either tool is missing or not executable. The previous -# install steps could fail silently, shipping an image whose every scan errored -# with "Missing required tools: trivy". -RUN trivy --version && hadolint --version +RUN trivy --version && hadolint --version && docker --version -# Build and install from a dedicated directory. /github/workspace is where the -# Action mounts the user's repository, so installing there both shipped the -# DockSec source to every user and left files that a bind mount then shadowed. WORKDIR /src COPY . . - -# Install DockSec with the AI extra: the image backs the GitHub Action, which -# exposes AI analysis inputs, so a scan-only install would make those inputs fail. RUN pip install --no-cache-dir ".[ai]" - -# Fail the build if the CLI itself is not importable and runnable. RUN docksec --version -# The Action mounts the repository being scanned here; it must start empty. -# Leaving /src first so the build sources can be removed rather than left behind. WORKDIR /github/workspace RUN rm -rf /src -# Copy and set permissions for entrypoint +RUN groupadd -g ${DOCKER_USER_GID} docksec && \ + useradd -m -u ${DOCKER_UID} -g docksec -s /sbin/nologin -c "DockSec App User" docksec + +RUN if getent group ${DOCKER_GID} >/dev/null; then \ + existing=$(getent group ${DOCKER_GID} | cut -d: -f1); \ + usermod -aG "$existing" docksec; \ + else \ + groupadd -g ${DOCKER_GID} docker_host && \ + usermod -aG docker_host docksec; \ + fi + +RUN mkdir -p /home/docksec/.docksec/results && \ + chown -R docksec:docksec /home/docksec/.docksec + COPY entrypoint.sh /entrypoint.sh -RUN chmod +x /entrypoint.sh +RUN chmod +x /entrypoint.sh && \ + chown docksec:docksec /entrypoint.sh && \ + chown -R docksec:docksec /github/workspace -# Set entrypoint ENTRYPOINT ["/entrypoint.sh"] diff --git a/entrypoint.sh b/entrypoint.sh index 73afa99..75044bf 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,11 +1,11 @@ #!/bin/bash set -e -# Set environment variables from inputs. -# Only export values that were actually provided: exporting an empty string is -# not the same as leaving a variable unset. An empty LLM_PROVIDER fails -# DocksecConfig validation and aborts the run with a traceback, even in -# --scan-only mode where no provider is needed at all. +if [ "$(id -u)" = "0" ] && [ -z "${GITHUB_WORKSPACE:-}" ]; then + echo "Standalone run detected: dropping privileges to 'docksec' user." + exec gosu docksec "$0" "$@" +fi + for var in OPENAI_API_KEY ANTHROPIC_API_KEY GOOGLE_API_KEY LLM_PROVIDER LLM_MODEL; do input_var="INPUT_${var}" if [ -n "${!input_var}" ]; then @@ -13,10 +13,6 @@ for var in OPENAI_API_KEY ANTHROPIC_API_KEY GOOGLE_API_KEY LLM_PROVIDER LLM_MODE fi done -# Run DockSec -# The inputs are passed as environment variables prefixed with INPUT_ -# e.g., inputs.dockerfile becomes INPUT_DOCKERFILE - ARGS=() if [ -n "${INPUT_DOCKERFILE}" ]; then @@ -31,9 +27,6 @@ if [ -n "${INPUT_COMPOSE}" ]; then ARGS+=("-c" "${INPUT_COMPOSE}") fi -# `output` is a deprecated alias for `output_dir` - the standalone -o/--output -# file flag was removed from the CLI, so both inputs now map to --output-dir. -# output_dir takes precedence if both are set. if [ -n "${INPUT_OUTPUT_DIR}" ]; then ARGS+=("--output-dir" "${INPUT_OUTPUT_DIR}") elif [ -n "${INPUT_OUTPUT}" ]; then @@ -68,13 +61,8 @@ if [ "${INPUT_IMAGE_ONLY}" = "true" ]; then ARGS+=("--image-only") fi -# Forward anything given on the command line. Without this the image only -# honours the INPUT_* variables, so `docker run ... --version` and every other -# direct CLI invocation fails with "Dockerfile path is required". ARGS+=("$@") -# printf runs its format once even for an empty array, so guard the log line: -# otherwise a bare `docksec` is reported as `docksec ''`. if [ ${#ARGS[@]} -eq 0 ]; then printf 'Running: docksec\n' else diff --git a/tests/smoke-test-nonroot.sh b/tests/smoke-test-nonroot.sh new file mode 100755 index 0000000..10f9f64 --- /dev/null +++ b/tests/smoke-test-nonroot.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# Smoke tests for non-root container hardening. +# +# These tests exercise the entrypoint.sh privilege-drop logic. They do NOT +# use --entrypoint to override the entrypoint, because doing so would bypass +# the very code path being tested. +set -euo pipefail + +IMAGE="${IMAGE:-docksec:smoke-test}" +DOCKER_GID="$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo 999)" +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +cleanup() { + docker rmi -f "$IMAGE" >/dev/null 2>&1 || true +} +trap cleanup EXIT + +echo "==> Building image (DOCKER_GID=$DOCKER_GID)..." +docker build \ + --build-arg "DOCKER_GID=$DOCKER_GID" \ + -t "$IMAGE" "$REPO_ROOT" + +echo "==> Test 1: standalone run must drop privileges (entrypoint.sh)" +OUT="$(docker run --rm "$IMAGE" --version 2>&1)" +echo " $OUT" | head -3 +if ! echo "$OUT" | grep -q "dropping privileges to 'docksec'"; then + echo "FAIL: entrypoint.sh did not drop privileges in standalone mode" >&2 + exit 1 +fi +echo " OK: standalone run drops privileges" + +echo "==> Test 2: CLI works as non-root" +docker run --rm "$IMAGE" --version >/dev/null +echo " OK: --version" +docker run --rm "$IMAGE" --help >/dev/null +echo " OK: --help" + +echo "==> Test 3: GitHub Action mode (GITHUB_WORKSPACE set) must NOT drop" +GH_OUT="$(docker run --rm -e GITHUB_WORKSPACE=/github/workspace "$IMAGE" --version 2>&1)" +echo " $GH_OUT" | head -3 +if echo "$GH_OUT" | grep -q "dropping privileges"; then + echo "FAIL: GH Action mode should NOT drop privileges" >&2 + exit 1 +fi +echo " OK: GH Action mode stays root" + +echo "==> Test 4: explicit --user override" +docker run --rm --user 0 "$IMAGE" --version >/dev/null +echo " OK: --user 0 override works" + +echo "" +echo "All smoke tests passed." From 1b4b7576d36085b2d74509fe84060efe7228533f Mon Sep 17 00:00:00 2001 From: Ashhad Ali Date: Mon, 19 Oct 2026 18:47:42 +0500 Subject: [PATCH 2/5] fix: clean up Dockerfile and restore entrypoint comments --- Dockerfile | 23 +++++++++++++++++++++++ entrypoint.sh | 28 ++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/Dockerfile b/Dockerfile index 4576e13..826a421 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,21 @@ FROM python:3.12-slim +# --- Pinned tool versions (reproducible builds) --- ARG TRIVY_VERSION=0.74.0 ARG HADOLINT_VERSION=2.15.1 ARG DOCKER_CLI_VERSION=27.3.1 + +# Host docker socket GID — pass with: +# --build-arg DOCKER_GID=$(stat -c '%g' /var/run/docker.sock) ARG DOCKER_GID=999 + +# Non-root user/group IDs ARG DOCKER_UID=10001 ARG DOCKER_USER_GID=10001 +# --- System dependencies --- +# docker.io is not available in Debian trixie, so the static Docker CLI binary +# is installed below instead. gosu is used by entrypoint.sh for privilege drop. RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ git \ @@ -14,6 +23,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gosu \ && rm -rf /var/lib/apt/lists/* +# --- Docker CLI (static binary, CLI only, no daemon) --- RUN set -eux; \ arch="$(dpkg --print-architecture)"; \ case "$arch" in \ @@ -29,6 +39,7 @@ RUN set -eux; \ rm -rf /tmp/docker /tmp/docker.tgz; \ docker --version +# --- Hadolint (pinned) --- RUN set -eux; \ arch="$(dpkg --print-architecture)"; \ case "$arch" in \ @@ -40,6 +51,7 @@ RUN set -eux; \ "https://github.com/hadolint/hadolint/releases/download/v${HADOLINT_VERSION}/hadolint-Linux-${hadolint_arch}"; \ chmod +x /usr/local/bin/hadolint +# --- Trivy (pinned release tarball) --- RUN set -eux; \ arch="$(dpkg --print-architecture)"; \ case "$arch" in \ @@ -52,19 +64,24 @@ RUN set -eux; \ tar -xzf /tmp/trivy.tar.gz -C /usr/local/bin trivy; \ rm -f /tmp/trivy.tar.gz +# Fail the build if any tool is missing or not executable RUN trivy --version && hadolint --version && docker --version +# --- Build DockSec --- WORKDIR /src COPY . . RUN pip install --no-cache-dir ".[ai]" RUN docksec --version +# Prepare workspace and clean build sources WORKDIR /github/workspace RUN rm -rf /src +# --- Non-root user (single creation) --- RUN groupadd -g ${DOCKER_USER_GID} docksec && \ useradd -m -u ${DOCKER_UID} -g docksec -s /sbin/nologin -c "DockSec App User" docksec +# --- Docker socket group (host GID match) --- RUN if getent group ${DOCKER_GID} >/dev/null; then \ existing=$(getent group ${DOCKER_GID} | cut -d: -f1); \ usermod -aG "$existing" docksec; \ @@ -73,12 +90,18 @@ RUN if getent group ${DOCKER_GID} >/dev/null; then \ usermod -aG docker_host docksec; \ fi +# --- DockSec results directory with correct ownership --- RUN mkdir -p /home/docksec/.docksec/results && \ chown -R docksec:docksec /home/docksec/.docksec +# --- Entrypoint --- COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh && \ chown docksec:docksec /entrypoint.sh && \ chown -R docksec:docksec /github/workspace +# NOTE: USER is intentionally not set. GitHub Docker container actions +# require root to access GITHUB_WORKSPACE. Standalone runs are dropped to +# the non-root `docksec` user by entrypoint.sh (via gosu). + ENTRYPOINT ["/entrypoint.sh"] diff --git a/entrypoint.sh b/entrypoint.sh index 75044bf..e887789 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,11 +1,27 @@ #!/bin/bash set -e +# --------------------------------------------------------------------------- +# Privilege dropping (non-root hardening) +# --------------------------------------------------------------------------- +# GitHub Docker container actions MUST run as root to access GITHUB_WORKSPACE. +# For standalone `docker run`, we drop to the non-root `docksec` user for +# least-privilege execution. Users can override with `--user`. +# +# Detection: +# - GITHUB_WORKSPACE is set -> GitHub Action mode -> stay root +# - UID != 0 -> already non-root -> continue +# - otherwise -> standalone -> drop to docksec if [ "$(id -u)" = "0" ] && [ -z "${GITHUB_WORKSPACE:-}" ]; then echo "Standalone run detected: dropping privileges to 'docksec' user." exec gosu docksec "$0" "$@" fi +# Set environment variables from inputs. +# Only export values that were actually provided: exporting an empty string is +# not the same as leaving a variable unset. An empty LLM_PROVIDER fails +# DocksecConfig validation and aborts the run with a traceback, even in +# --scan-only mode where no provider is needed at all. for var in OPENAI_API_KEY ANTHROPIC_API_KEY GOOGLE_API_KEY LLM_PROVIDER LLM_MODEL; do input_var="INPUT_${var}" if [ -n "${!input_var}" ]; then @@ -13,6 +29,10 @@ for var in OPENAI_API_KEY ANTHROPIC_API_KEY GOOGLE_API_KEY LLM_PROVIDER LLM_MODE fi done +# Run DockSec +# The inputs are passed as environment variables prefixed with INPUT_ +# e.g., inputs.dockerfile becomes INPUT_DOCKERFILE + ARGS=() if [ -n "${INPUT_DOCKERFILE}" ]; then @@ -27,6 +47,9 @@ if [ -n "${INPUT_COMPOSE}" ]; then ARGS+=("-c" "${INPUT_COMPOSE}") fi +# `output` is a deprecated alias for `output_dir` - the standalone -o/--output +# file flag was removed from the CLI, so both inputs now map to --output-dir. +# output_dir takes precedence if both are set. if [ -n "${INPUT_OUTPUT_DIR}" ]; then ARGS+=("--output-dir" "${INPUT_OUTPUT_DIR}") elif [ -n "${INPUT_OUTPUT}" ]; then @@ -61,8 +84,13 @@ if [ "${INPUT_IMAGE_ONLY}" = "true" ]; then ARGS+=("--image-only") fi +# Forward anything given on the command line. Without this the image only +# honours the INPUT_* variables, so `docker run ... --version` and every other +# direct CLI invocation fails with "Dockerfile path is required". ARGS+=("$@") +# printf runs its format once even for an empty array, so guard the log line: +# otherwise a bare `docksec` is reported as `docksec ''`. if [ ${#ARGS[@]} -eq 0 ]; then printf 'Running: docksec\n' else From 3ef91692ad2446b647ff202d50f00c7cd16cc257 Mon Sep 17 00:00:00 2001 From: Ashhad Ali Date: Mon, 19 Oct 2026 18:49:36 +0500 Subject: [PATCH 3/5] fix(docker): place arm64 case before tool names in comments --- Dockerfile | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/Dockerfile b/Dockerfile index 826a421..9b7e67a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,9 +13,7 @@ ARG DOCKER_GID=999 ARG DOCKER_UID=10001 ARG DOCKER_USER_GID=10001 -# --- System dependencies --- -# docker.io is not available in Debian trixie, so the static Docker CLI binary -# is installed below instead. gosu is used by entrypoint.sh for privilege drop. +# System dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ git \ @@ -23,7 +21,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gosu \ && rm -rf /var/lib/apt/lists/* -# --- Docker CLI (static binary, CLI only, no daemon) --- +# Docker CLI (static binary) RUN set -eux; \ arch="$(dpkg --print-architecture)"; \ case "$arch" in \ @@ -39,7 +37,7 @@ RUN set -eux; \ rm -rf /tmp/docker /tmp/docker.tgz; \ docker --version -# --- Hadolint (pinned) --- +# Linter install RUN set -eux; \ arch="$(dpkg --print-architecture)"; \ case "$arch" in \ @@ -51,7 +49,7 @@ RUN set -eux; \ "https://github.com/hadolint/hadolint/releases/download/v${HADOLINT_VERSION}/hadolint-Linux-${hadolint_arch}"; \ chmod +x /usr/local/bin/hadolint -# --- Trivy (pinned release tarball) --- +# Scanner install RUN set -eux; \ arch="$(dpkg --print-architecture)"; \ case "$arch" in \ @@ -64,24 +62,22 @@ RUN set -eux; \ tar -xzf /tmp/trivy.tar.gz -C /usr/local/bin trivy; \ rm -f /tmp/trivy.tar.gz -# Fail the build if any tool is missing or not executable +# Fail the build if any tool is missing RUN trivy --version && hadolint --version && docker --version -# --- Build DockSec --- WORKDIR /src COPY . . RUN pip install --no-cache-dir ".[ai]" RUN docksec --version -# Prepare workspace and clean build sources WORKDIR /github/workspace RUN rm -rf /src -# --- Non-root user (single creation) --- +# Non-root user RUN groupadd -g ${DOCKER_USER_GID} docksec && \ useradd -m -u ${DOCKER_UID} -g docksec -s /sbin/nologin -c "DockSec App User" docksec -# --- Docker socket group (host GID match) --- +# Docker socket group (host GID match) RUN if getent group ${DOCKER_GID} >/dev/null; then \ existing=$(getent group ${DOCKER_GID} | cut -d: -f1); \ usermod -aG "$existing" docksec; \ @@ -90,18 +86,14 @@ RUN if getent group ${DOCKER_GID} >/dev/null; then \ usermod -aG docker_host docksec; \ fi -# --- DockSec results directory with correct ownership --- +# DockSec results directory RUN mkdir -p /home/docksec/.docksec/results && \ chown -R docksec:docksec /home/docksec/.docksec -# --- Entrypoint --- +# Entrypoint COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh && \ chown docksec:docksec /entrypoint.sh && \ chown -R docksec:docksec /github/workspace -# NOTE: USER is intentionally not set. GitHub Docker container actions -# require root to access GITHUB_WORKSPACE. Standalone runs are dropped to -# the non-root `docksec` user by entrypoint.sh (via gosu). - ENTRYPOINT ["/entrypoint.sh"] From fbdfe43b2a5710a374448086db0a60b2daa91665 Mon Sep 17 00:00:00 2001 From: Ashhad Ali Date: Mon, 19 Oct 2026 18:59:33 +0500 Subject: [PATCH 4/5] fix(docker): clean up comments --- Dockerfile | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9b7e67a..ee8bfa9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,19 +1,14 @@ FROM python:3.12-slim -# --- Pinned tool versions (reproducible builds) --- +# Pinned tool versions ARG TRIVY_VERSION=0.74.0 ARG HADOLINT_VERSION=2.15.1 ARG DOCKER_CLI_VERSION=27.3.1 -# Host docker socket GID — pass with: -# --build-arg DOCKER_GID=$(stat -c '%g' /var/run/docker.sock) ARG DOCKER_GID=999 - -# Non-root user/group IDs ARG DOCKER_UID=10001 ARG DOCKER_USER_GID=10001 -# System dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ git \ @@ -73,11 +68,9 @@ RUN docksec --version WORKDIR /github/workspace RUN rm -rf /src -# Non-root user RUN groupadd -g ${DOCKER_USER_GID} docksec && \ useradd -m -u ${DOCKER_UID} -g docksec -s /sbin/nologin -c "DockSec App User" docksec -# Docker socket group (host GID match) RUN if getent group ${DOCKER_GID} >/dev/null; then \ existing=$(getent group ${DOCKER_GID} | cut -d: -f1); \ usermod -aG "$existing" docksec; \ @@ -86,11 +79,9 @@ RUN if getent group ${DOCKER_GID} >/dev/null; then \ usermod -aG docker_host docksec; \ fi -# DockSec results directory RUN mkdir -p /home/docksec/.docksec/results && \ chown -R docksec:docksec /home/docksec/.docksec -# Entrypoint COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh && \ chown docksec:docksec /entrypoint.sh && \ From 70bc9c4b2b8ecbca66ae39aeebc8c7fbd6879f73 Mon Sep 17 00:00:00 2001 From: Ashhad Ali Date: Mon, 26 Oct 2026 16:00:34 +0500 Subject: [PATCH 5/5] fix(docker): install Docker CLI from GPG-signed APT repo --- Dockerfile | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/Dockerfile b/Dockerfile index ee8bfa9..3ac9571 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,5 @@ FROM python:3.12-slim -# Pinned tool versions -ARG TRIVY_VERSION=0.74.0 -ARG HADOLINT_VERSION=2.15.1 -ARG DOCKER_CLI_VERSION=27.3.1 - ARG DOCKER_GID=999 ARG DOCKER_UID=10001 ARG DOCKER_USER_GID=10001 @@ -16,23 +11,25 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gosu \ && rm -rf /var/lib/apt/lists/* -# Docker CLI (static binary) -RUN set -eux; \ - arch="$(dpkg --print-architecture)"; \ - case "$arch" in \ - amd64) docker_arch='x86_64' ;; \ - arm64) docker_arch='aarch64' ;; \ - *) echo "unsupported architecture: $arch" >&2; exit 1 ;; \ - esac; \ - curl -fsSL -o /tmp/docker.tgz \ - "https://download.docker.com/linux/static/stable/${docker_arch}/docker-${DOCKER_CLI_VERSION}.tgz"; \ - tar -xzf /tmp/docker.tgz -C /tmp; \ - mv /tmp/docker/docker /usr/local/bin/docker; \ - chmod +x /usr/local/bin/docker; \ - rm -rf /tmp/docker /tmp/docker.tgz; \ - docker --version +# Docker CLI (GPG-signed APT repository) +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + gnupg \ + && install -m 0755 -d /etc/apt/keyrings \ + && curl -fsSL https://download.docker.com/linux/debian/gpg \ + -o /etc/apt/keyrings/docker.asc \ + && chmod a+r /etc/apt/keyrings/docker.asc \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \ + https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \ + > /etc/apt/sources.list.d/docker.list \ + && apt-get update \ + && apt-get install -y --no-install-recommends docker-ce-cli \ + && rm -rf /var/lib/apt/lists/* \ + && docker --version # Linter install +ARG HADOLINT_VERSION=2.15.1 RUN set -eux; \ arch="$(dpkg --print-architecture)"; \ case "$arch" in \ @@ -45,6 +42,7 @@ RUN set -eux; \ chmod +x /usr/local/bin/hadolint # Scanner install +ARG TRIVY_VERSION=0.74.0 RUN set -eux; \ arch="$(dpkg --print-architecture)"; \ case "$arch" in \