- Add init container to set up config files with correct ownership - Run main container as socktop user (UID 100, GID 101) from the start - Use fsGroup to ensure proper volume permissions - Add emptyDir volume for /var/lib/socktop to avoid permission issues - Create docker-entrypoint.sh wrapper to detect root vs non-root execution - Root mode: uses init-config.sh for Docker/docker-compose - Non-root mode: directly runs entrypoint.sh for K8s - Update deployment command format to work with new entrypoint This resolves 'Operation not permitted' errors when running in K8s with security contexts that restrict user switching and ownership changes.
140 lines
4.7 KiB
Docker
140 lines
4.7 KiB
Docker
# Multi-stage Dockerfile for socktop webterm
|
|
# This reduces the final image size significantly by separating build and runtime
|
|
|
|
# ============================================================================
|
|
# Stage 1: Rust Builder
|
|
# ============================================================================
|
|
FROM rust:1.91-slim-bookworm AS rust-builder
|
|
|
|
WORKDIR /build
|
|
|
|
# Install build dependencies
|
|
RUN apt-get update && \
|
|
apt-get install -y --no-install-recommends \
|
|
pkg-config \
|
|
libssl-dev \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Copy only dependency files first for better caching
|
|
COPY Cargo.toml Cargo.lock ./
|
|
|
|
# Create dummy source to cache dependencies
|
|
RUN mkdir src && \
|
|
echo "fn main() {}" > src/server.rs && \
|
|
echo "pub fn lib() {}" > src/lib.rs && \
|
|
cargo build --release && \
|
|
rm -rf src target/release/webterm-server target/release/deps/webterm*
|
|
|
|
# Copy actual source code
|
|
COPY src ./src
|
|
COPY templates ./templates
|
|
COPY static ./static
|
|
|
|
# Build the actual application (force rebuild by touching sources)
|
|
RUN touch src/server.rs src/lib.rs && \
|
|
cargo build --release && \
|
|
strip target/release/webterm-server
|
|
|
|
# ============================================================================
|
|
# Stage 2: Node.js Builder
|
|
# ============================================================================
|
|
FROM node:20-slim AS node-builder
|
|
|
|
WORKDIR /build
|
|
|
|
# Copy package files
|
|
COPY package.json package-lock.json ./
|
|
COPY static ./static
|
|
|
|
# Install only production dependencies
|
|
RUN npm ci --only=production && \
|
|
# Copy static files to node_modules for serving
|
|
cp static/terminado-addon.js node_modules/ && \
|
|
cp static/bg.png node_modules/ && \
|
|
cp static/styles.css node_modules/ && \
|
|
cp static/terminal.js node_modules/ && \
|
|
cp static/favicon.png node_modules/
|
|
|
|
# ============================================================================
|
|
# Stage 3: Runtime Image
|
|
# ============================================================================
|
|
FROM debian:trixie-slim
|
|
|
|
# Avoid prompts from apt
|
|
ENV DEBIAN_FRONTEND=noninteractive
|
|
ENV TERM=xterm-256color
|
|
|
|
# Install only runtime dependencies
|
|
RUN apt-get update && \
|
|
apt-get upgrade -y && \
|
|
apt-get install -y --no-install-recommends \
|
|
# Runtime libraries
|
|
libssl3 \
|
|
ca-certificates \
|
|
# For socktop packages
|
|
curl \
|
|
gnupg2 \
|
|
# Shell and utilities
|
|
bash \
|
|
procps \
|
|
# Health check
|
|
curl \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Add socktop APT repository and install packages
|
|
RUN curl -fsSL https://jasonwitty.github.io/socktop/KEY.gpg | \
|
|
gpg --dearmor -o /usr/share/keyrings/socktop-archive-keyring.gpg && \
|
|
echo "deb [signed-by=/usr/share/keyrings/socktop-archive-keyring.gpg] https://jasonwitty.github.io/socktop stable main" > /etc/apt/sources.list.d/socktop.list && \
|
|
apt-get update && \
|
|
apt-get install -y --no-install-recommends socktop socktop-agent && \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
# Create application user (if not already exists from socktop packages)
|
|
RUN id -u socktop &>/dev/null || useradd -m -s /bin/bash socktop && \
|
|
mkdir -p /home/socktop/.config/socktop && \
|
|
chown -R socktop:socktop /home/socktop
|
|
|
|
# Set working directory
|
|
WORKDIR /app
|
|
|
|
# Copy built binary from rust-builder
|
|
COPY --from=rust-builder /build/target/release/webterm-server /usr/local/bin/webterm-server
|
|
|
|
# Copy templates and static files
|
|
COPY --from=rust-builder /build/templates ./templates
|
|
COPY --from=rust-builder /build/static ./static
|
|
|
|
# Copy node_modules from node-builder
|
|
COPY --from=node-builder /build/node_modules ./node_modules
|
|
|
|
# Copy runtime scripts
|
|
COPY docker/entrypoint.sh /entrypoint.sh
|
|
COPY docker/init-config.sh /init-config.sh
|
|
COPY docker/restricted-shell.sh /usr/local/bin/restricted-shell.sh
|
|
RUN chmod +x /entrypoint.sh /init-config.sh /usr/local/bin/restricted-shell.sh
|
|
|
|
# Expose ports
|
|
# 8082 - webterm HTTP server
|
|
# 3001 - socktop agent (if used)
|
|
EXPOSE 8082 3001
|
|
|
|
# Health check
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
CMD curl -f http://localhost:8082/ || exit 1
|
|
|
|
# Create a wrapper script that detects if running as root or socktop user
|
|
RUN echo '#!/bin/bash\n\
|
|
if [ "$(id -u)" -eq 0 ]; then\n\
|
|
# Running as root - use init-config.sh to set up and switch to socktop\n\
|
|
exec /init-config.sh "$@"\n\
|
|
else\n\
|
|
# Running as socktop user - directly execute entrypoint\n\
|
|
exec /entrypoint.sh "$@"\n\
|
|
fi' > /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh
|
|
|
|
# Set entrypoint to the wrapper
|
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
|
|
|
# Default command - use restricted shell that only allows socktop commands
|
|
CMD ["webterm-server", "--host", "0.0.0.0", "--port", "8082", "--command", "/usr/local/bin/restricted-shell.sh"]
|