fix: Address Dockerfile issues identified by toolbox-qadocker audit
This commit fixes several issues in the toolbox-base Dockerfile that were identified during the audit: - Added SHELL directive with pipefail option where pipes are used - Fixed syntax error in user creation logic by changing 'else if' to 'elif' - Removed problematic 'cd' usage, replacing with 'git -C' for directory-specific operations - Added SHELL directive to second stage where pipes are used - Improved multi-line RUN command formatting with proper semicolon usage These changes resolve the following Hadolint errors: - DL4006: Missing pipefail in RUN commands with pipes - SC1075: Incorrect use of 'else if' instead of 'elif' - DL3003: Usage of 'cd' instead of WORKDIR The Dockerfile now passes Hadolint validation when ignoring version pinning and multiple RUN command warnings, which are expected in this context.
This commit is contained in:
@@ -57,6 +57,7 @@ RUN ln -sf /usr/bin/fdfind /usr/local/bin/fd \
|
|||||||
&& ln -sf /usr/bin/batcat /usr/local/bin/bat
|
&& ln -sf /usr/bin/batcat /usr/local/bin/bat
|
||||||
|
|
||||||
# ROOT: Install Gitea tea CLI (system-wide)
|
# ROOT: Install Gitea tea CLI (system-wide)
|
||||||
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
RUN curl -fsSL "https://dl.gitea.io/tea/${TEA_VERSION}/tea-${TEA_VERSION}-linux-amd64" -o /tmp/tea \
|
RUN curl -fsSL "https://dl.gitea.io/tea/${TEA_VERSION}/tea-${TEA_VERSION}-linux-amd64" -o /tmp/tea \
|
||||||
&& curl -fsSL "https://dl.gitea.io/tea/${TEA_VERSION}/tea-${TEA_VERSION}-linux-amd64.sha256" -o /tmp/tea.sha256 \
|
&& curl -fsSL "https://dl.gitea.io/tea/${TEA_VERSION}/tea-${TEA_VERSION}-linux-amd64.sha256" -o /tmp/tea.sha256 \
|
||||||
&& sed -n 's/ .*//p' /tmp/tea.sha256 | awk '{print $1 " /tmp/tea"}' | sha256sum -c - \
|
&& sed -n 's/ .*//p' /tmp/tea.sha256 | awk '{print $1 " /tmp/tea"}' | sha256sum -c - \
|
||||||
@@ -70,27 +71,32 @@ ENV LANG=en_US.UTF-8 \
|
|||||||
LC_ALL=en_US.UTF-8
|
LC_ALL=en_US.UTF-8
|
||||||
|
|
||||||
# ROOT: Install Starship prompt (system-wide)
|
# ROOT: Install Starship prompt (system-wide)
|
||||||
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
RUN curl -fsSL https://starship.rs/install.sh | sh -s -- -y -b /usr/local/bin
|
RUN curl -fsSL https://starship.rs/install.sh | sh -s -- -y -b /usr/local/bin
|
||||||
|
|
||||||
# Install aqua package manager (manages additional CLI tooling)
|
# Install aqua package manager (manages additional CLI tooling)
|
||||||
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
RUN curl -sSfL https://raw.githubusercontent.com/aquaproj/aqua-installer/v2.3.1/aqua-installer | AQUA_ROOT_DIR=/usr/local/share/aquaproj-aqua bash \
|
RUN curl -sSfL https://raw.githubusercontent.com/aquaproj/aqua-installer/v2.3.1/aqua-installer | AQUA_ROOT_DIR=/usr/local/share/aquaproj-aqua bash \
|
||||||
&& ln -sf /usr/local/share/aquaproj-aqua/bin/aqua /usr/local/bin/aqua
|
&& ln -sf /usr/local/share/aquaproj-aqua/bin/aqua /usr/local/bin/aqua
|
||||||
|
|
||||||
# Install mise for runtime management (no global toolchains pre-installed)
|
# Install mise for runtime management (no global toolchains pre-installed)
|
||||||
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
RUN curl -sSfL https://mise.jdx.dev/install.sh | env MISE_INSTALL_PATH=/usr/local/bin/mise MISE_INSTALL_HELP=0 sh
|
RUN curl -sSfL https://mise.jdx.dev/install.sh | env MISE_INSTALL_PATH=/usr/local/bin/mise MISE_INSTALL_HELP=0 sh
|
||||||
|
|
||||||
# Install Node.js via mise to enable npm package installation
|
# Install Node.js via mise to enable npm package installation
|
||||||
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
RUN mise install node@22.13.0 && mise global node@22.13.0
|
RUN mise install node@22.13.0 && mise global node@22.13.0
|
||||||
|
|
||||||
# Create non-root user with matching UID/GID for host mapping
|
# Create non-root user with matching UID/GID for host mapping
|
||||||
# Check if user/group already exists and handle appropriately
|
# Check if user/group already exists and handle appropriately
|
||||||
RUN if getent passwd "${USER_ID}" >/dev/null; then \
|
RUN set -eux; \
|
||||||
|
if getent passwd "${USER_ID}" >/dev/null; then \
|
||||||
existing_user="$(getent passwd "${USER_ID}" | cut -d: -f1)"; \
|
existing_user="$(getent passwd "${USER_ID}" | cut -d: -f1)"; \
|
||||||
echo "User with UID ${USER_ID} already exists: ${existing_user}" >&2; \
|
echo "User with UID ${USER_ID} already exists: ${existing_user}" >&2; \
|
||||||
else \
|
elif ! getent group "${GROUP_ID}" >/dev/null; then \
|
||||||
if ! getent group "${GROUP_ID}" >/dev/null; then \
|
|
||||||
groupadd --gid "${GROUP_ID}" "${USERNAME}"; \
|
groupadd --gid "${GROUP_ID}" "${USERNAME}"; \
|
||||||
fi \
|
useradd --uid "${USER_ID}" --gid "${GROUP_ID}" --shell /usr/bin/zsh --create-home "${USERNAME}"; \
|
||||||
|
else \
|
||||||
useradd --uid "${USER_ID}" --gid "${GROUP_ID}" --shell /usr/bin/zsh --create-home "${USERNAME}"; \
|
useradd --uid "${USER_ID}" --gid "${GROUP_ID}" --shell /usr/bin/zsh --create-home "${USERNAME}"; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -101,6 +107,9 @@ RUN chown -R "${USER_ID}:${GROUP_ID}" "/home/${USERNAME}"
|
|||||||
USER ${USERNAME}
|
USER ${USERNAME}
|
||||||
WORKDIR /home/${USERNAME}
|
WORKDIR /home/${USERNAME}
|
||||||
|
|
||||||
|
# Ensure the workspace directory exists with proper permissions
|
||||||
|
RUN mkdir -p /workspace && chmod 755 /workspace
|
||||||
|
|
||||||
# NON-ROOT: Install mise runtime manager for toolbox user
|
# NON-ROOT: Install mise runtime manager for toolbox user
|
||||||
RUN curl -sSfL https://mise.jdx.dev/install.sh | sh
|
RUN curl -sSfL https://mise.jdx.dev/install.sh | sh
|
||||||
|
|
||||||
@@ -166,9 +175,8 @@ RUN mise exec -- npm install -g bats@1.11.0 && mise reshim
|
|||||||
|
|
||||||
# NON-ROOT: Install BATS testing framework from source (baked into image)
|
# NON-ROOT: Install BATS testing framework from source (baked into image)
|
||||||
RUN git clone https://github.com/bats-core/bats-core.git /tmp/bats-core \
|
RUN git clone https://github.com/bats-core/bats-core.git /tmp/bats-core \
|
||||||
&& cd /tmp/bats-core \
|
&& git -C /tmp/bats-core checkout v1.11.0 \
|
||||||
&& git checkout v1.11.0 \
|
&& /tmp/bats-core/install.sh "$HOME/.local" \
|
||||||
&& ./install.sh "$HOME/.local" \
|
|
||||||
&& rm -rf /tmp/bats-core
|
&& rm -rf /tmp/bats-core
|
||||||
|
|
||||||
# Prepare workspace directory with appropriate ownership
|
# Prepare workspace directory with appropriate ownership
|
||||||
@@ -178,6 +186,8 @@ RUN mkdir -p /workspace \
|
|||||||
# Remove sudo to ensure no root escalation is possible at runtime
|
# Remove sudo to ensure no root escalation is possible at runtime
|
||||||
RUN apt-get remove -y sudo 2>/dev/null || true && apt-get autoremove -y 2>/dev/null || true && rm -rf /var/lib/apt/lists/* 2>/dev/null || true
|
RUN apt-get remove -y sudo 2>/dev/null || true && apt-get autoremove -y 2>/dev/null || true && rm -rf /var/lib/apt/lists/* 2>/dev/null || true
|
||||||
|
|
||||||
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
|
|
||||||
ENV SHELL=/usr/bin/zsh \
|
ENV SHELL=/usr/bin/zsh \
|
||||||
AQUA_GLOBAL_CONFIG=/home/${USERNAME}/.config/aquaproj-aqua/aqua.yaml \
|
AQUA_GLOBAL_CONFIG=/home/${USERNAME}/.config/aquaproj-aqua/aqua.yaml \
|
||||||
PATH=/home/${USERNAME}/.local/share/aquaproj-aqua/bin:/home/${USERNAME}/.local/share/mise/shims:/home/${USERNAME}/.local/bin:${PATH}
|
PATH=/home/${USERNAME}/.local/share/aquaproj-aqua/bin:/home/${USERNAME}/.local/share/mise/shims:/home/${USERNAME}/.local/bin:${PATH}
|
||||||
@@ -244,19 +254,21 @@ ENV LANG=en_US.UTF-8 \
|
|||||||
LC_ALL=en_US.UTF-8
|
LC_ALL=en_US.UTF-8
|
||||||
|
|
||||||
# ROOT: Create user/group structure
|
# ROOT: Create user/group structure
|
||||||
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
# First clean up any existing user/group with the same ID
|
# First clean up any existing user/group with the same ID
|
||||||
RUN if getent passwd "${USER_ID}" >/dev/null; then \
|
RUN set -eux; \
|
||||||
|
if getent passwd "${USER_ID}" >/dev/null; then \
|
||||||
existing_user="$(getent passwd "${USER_ID}" | cut -d: -f1)"; \
|
existing_user="$(getent passwd "${USER_ID}" | cut -d: -f1)"; \
|
||||||
userdel --remove "${existing_user}"; \
|
userdel --remove "${existing_user}"; \
|
||||||
fi \
|
fi; \
|
||||||
&& if getent group "${GROUP_ID}" >/dev/null; then \
|
if getent group "${GROUP_ID}" >/dev/null; then \
|
||||||
groupdel "$(getent group "${GROUP_ID}" | cut -d: -f1)"; \
|
groupdel "$(getent group "${GROUP_ID}" | cut -d: -f1)"; \
|
||||||
fi \
|
fi; \
|
||||||
# Create the group and user
|
# Create the group and user
|
||||||
&& groupadd --gid "${GROUP_ID}" "${USERNAME}" \
|
groupadd --gid "${GROUP_ID}" "${USERNAME}"; \
|
||||||
&& useradd --uid "${USER_ID}" --gid "${GROUP_ID}" --shell /usr/bin/zsh --create-home "${USERNAME}" \
|
useradd --uid "${USER_ID}" --gid "${GROUP_ID}" --shell /usr/bin/zsh --create-home "${USERNAME}"; \
|
||||||
# Ensure proper ownership of home directory
|
# Ensure proper ownership of home directory
|
||||||
&& chown -R "${USER_ID}:${GROUP_ID}" "/home/${USERNAME}"
|
chown -R "${USER_ID}:${GROUP_ID}" "/home/${USERNAME}"
|
||||||
|
|
||||||
# ROOT: Copy the complete user environment from the installer stage
|
# ROOT: Copy the complete user environment from the installer stage
|
||||||
COPY --from=installer --chown=${USER_ID}:${GROUP_ID} /home/${USERNAME} /home/${USERNAME}
|
COPY --from=installer --chown=${USER_ID}:${GROUP_ID} /home/${USERNAME} /home/${USERNAME}
|
||||||
@@ -265,6 +277,7 @@ COPY --from=installer --chown=${USER_ID}:${GROUP_ID} /home/${USERNAME} /home/${U
|
|||||||
RUN mkdir -p /workspace && chown "${USER_ID}:${GROUP_ID}" /workspace
|
RUN mkdir -p /workspace && chown "${USER_ID}:${GROUP_ID}" /workspace
|
||||||
|
|
||||||
# ROOT: Install system-wide tools (tea and starship) which were in the source image
|
# ROOT: Install system-wide tools (tea and starship) which were in the source image
|
||||||
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
RUN curl -fsSL "https://dl.gitea.io/tea/${TEA_VERSION}/tea-${TEA_VERSION}-linux-amd64" -o /tmp/tea \
|
RUN curl -fsSL "https://dl.gitea.io/tea/${TEA_VERSION}/tea-${TEA_VERSION}-linux-amd64" -o /tmp/tea \
|
||||||
&& curl -fsSL "https://dl.gitea.io/tea/${TEA_VERSION}/tea-${TEA_VERSION}-linux-amd64.sha256" -o /tmp/tea.sha256 \
|
&& curl -fsSL "https://dl.gitea.io/tea/${TEA_VERSION}/tea-${TEA_VERSION}-linux-amd64.sha256" -o /tmp/tea.sha256 \
|
||||||
&& sed -n 's/ .*//p' /tmp/tea.sha256 | awk '{print $1 " /tmp/tea"}' | sha256sum -c - \
|
&& sed -n 's/ .*//p' /tmp/tea.sha256 | awk '{print $1 " /tmp/tea"}' | sha256sum -c - \
|
||||||
@@ -281,6 +294,8 @@ ENV PATH=/home/${USERNAME}/.local/share/aquaproj-aqua/bin:/home/${USERNAME}/.loc
|
|||||||
ENV SHELL=/usr/bin/zsh \
|
ENV SHELL=/usr/bin/zsh \
|
||||||
AQUA_GLOBAL_CONFIG=/home/${USERNAME}/.config/aquaproj-aqua/aqua.yaml
|
AQUA_GLOBAL_CONFIG=/home/${USERNAME}/.config/aquaproj-aqua/aqua.yaml
|
||||||
|
|
||||||
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
|
|
||||||
# FINAL USER: Switch to toolbox user for runtime
|
# FINAL USER: Switch to toolbox user for runtime
|
||||||
USER ${USERNAME}
|
USER ${USERNAME}
|
||||||
WORKDIR /workspace
|
WORKDIR /workspace
|
||||||
|
|||||||
Reference in New Issue
Block a user