# https://www.debian.org/releases/ # https://hub.docker.com/_/debian # We use codename (bookworm) instead of version number (12) because we want to select # the matching Python Docker image, which is named after the codename only. # bookworm-20241016 corresponds to Debian 12.7 ARG DEBIAN_CODENAME=bookworm # Debian codenamed images are tagged with date codes rather than minor version numbers. ARG DEBIAN_DATECODE=20241223 # Find the current version of Python at https://www.python.org/downloads/source/ ARG PYTHON_VERSION=3.12.8 # https://github.com/ahmetb/kubectx/releases ARG KUBECTX_COMPLETION_VERSION=0.9.5 # https://github.com/jonmosco/kube-ps1/releases ARG KUBE_PS1_VERSION=0.9.0 # https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html#plugin-version-history ARG SESSION_MANAGER_PLUGIN_VERSION=latest # Helm plugins: # https://github.com/databus23/helm-diff/releases ARG HELM_DIFF_VERSION=3.9.13 # https://github.com/aslafy-z/helm-git/releases ARG HELM_GIT_VERSION=1.3.0 FROM rust:1-${DEBIAN_CODENAME} AS rust COPY /src/colorsaurus /src/colorsaurus WORKDIR /src/colorsaurus RUN cargo install --path . --root /usr/local FROM python:${PYTHON_VERSION}-slim-${DEBIAN_CODENAME} AS python # Debian comes with minimal Locale support. See https://github.com/docker-library/docs/pull/703/files # Recommended: LC_ALL=C.UTF-8 ENV LC_ALL=C.UTF-8 # Once again, Debian is weird. Package-installed Python is system-only, and does not # play well with pip. See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=765022#30 # and https://wiki.debian.org/Python#Deviations_from_upstream # # So we copy python from the Docker "Official Image" for python, (not to be confused with # any official python image provided by python upstream). See https://hub.docker.com/_/python/ for details. # # Bad is the fact that python, being an interpreted language, installs a lot of shell scripts # that specifically reference the location of the python interpreter or other things, those # locations being baked in at install time. So it does not work to install python in `/dist` # and then later copy `/dist` to `/usr/local`: The installed scripts would have `!#/dist/bin/python` # baked in and fail. So the official image starts with a basically empty /usr/local/, # installs python into /usr/local, and then we copy /usr/local over. # # Build the Python packages, configured to use /usr/local/bin/python3, and install them under /usr/local COPY requirements.txt /requirements.txt RUN python3 -m pip install --upgrade --progress-bar off pip setuptools wheel && \ pip install --progress-bar off -r /requirements.txt --prefix=/usr/local --no-build-isolation # Remove Python cache files RUN find / -xdev -name __pycache__ -exec rm -rf {} \; -prune # # Geodesic base image # FROM debian:${DEBIAN_CODENAME}-${DEBIAN_DATECODE}-slim ARG VERSION ENV GEODESIC_VERSION=$VERSION ENV GEODESIC_OS=debian # TARGETARCH and TARGETOS are defined by buildkit, but not available with other builders ARG TARGETARCH ARG TARGETOS RUN [ -n "$TARGETARCH" ] && [ -n "$TARGETOS" ] || (echo "Geodesic must be built with buildkit."; echo "See: https://docs.docker.com/build/buildkit/"; false) RUN [ "$TARGETARCH" = "amd64" ] || [ "$TARGETARCH" = "arm64" ] || (echo "Unsupported TARGETARCH: \"$TARGETARCH\"" && false) RUN [ "$TARGETOS" = "linux" ] || (echo "Unsupported TARGETOS: \"$TARGETOS\"" && false) # Set a default terminal to "dumb" (headless) to make `tput` happy when running scripts. # When we launch Geodesic for interactive use, we forward the host value of `TERM` ENV TERM=dumb # Debian comes with minimal Locale support. See https://github.com/docker-library/docs/pull/703/files # Recommended: LC_ALL=C.UTF-8 ENV LC_ALL=C.UTF-8 # Set XDG environment variables per https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html # This is not a "multi-user" system, so we'll use special directories under # - /etc as the global configuration dir instead of default $HOME/.config # - /usr/share as the global data dir instead of default $HOME/.local/share # - /tmp as the global cache dir instead of default $HOME/.cache # This allows daemon/server users like Atlantis to use the same # configuration as the root user, which is usually what we want. # If the daemon wants isolation, it can unset the variables # or set them to something else. # We leave the runtime dir unset/default since that is specifically # required to be owned by the current user. # Read more: ENV XDG_DATA_HOME=/usr/share/xdg_data_home ENV XDG_CONFIG_HOME=/etc/xdg_config_home ENV XDG_CACHE_HOME=/var/cache/xdg_cache_home RUN for dir in $XDG_DATA_HOME $XDG_CONFIG_HOME $XDG_CACHE_HOME; do \ mkdir -p $dir; chmod 777 $dir; done ENV BANNER="geodesic" # Install all packages as root USER root # We used to override user home directory to /conf, but we no longer do that. ENV HOME=/root # Keep dpkg quiet about running non-interactively RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections # Make Cloud Posse repo the preference for `kubectl` because # the Google Cloud SDK repo uses a different versioning scheme COPY os/debian/rootfs/etc/apt/preferences.d/kubectl-preferences /etc/apt/preferences.d/kubectl-preferences COPY packages.txt packages-amd64-only.txt os/debian/packages-debian.txt /etc/apt/ ## Here is where we would copy in the repo checksum in an attempt to ensure updates bust the Docker build cache # Add CloudPosse package repo RUN apt-get update && apt-get install -y apt-utils curl RUN curl -1sLf 'https://dl.cloudsmith.io/public/cloudposse/packages/cfg/setup/bash.deb.sh' | bash # Add OpenTofu package repo RUN curl -fsSL https://get.opentofu.org/opentofu.gpg > /etc/apt/keyrings/opentofu.gpg && \ curl -fsSL https://packages.opentofu.org/opentofu/tofu/gpgkey | \ gpg --no-tty --batch --dearmor -o /etc/apt/keyrings/opentofu-repo.gpg >/dev/null && \ chmod a+r /etc/apt/keyrings/opentofu.gpg /etc/apt/keyrings/opentofu-repo.gpg && \ printf "%s [signed-by=/etc/apt/keyrings/opentofu.gpg,/etc/apt/keyrings/opentofu-repo.gpg] https://packages.opentofu.org/opentofu/tofu/any/ any main\n" \ "deb" "deb-src" > /etc/apt/sources.list.d/opentofu.list && \ chmod a+r /etc/apt/sources.list.d/opentofu.list # Install Google package repo RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" \ > /etc/apt/sources.list.d/google-cloud-sdk.list && \ curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg # Install packages (but only explicitly listed ones) RUN apt-get update && apt-get install -y --no-install-recommends \ $(grep -h -v '^#' /etc/apt/packages.txt /etc/apt/packages-debian.txt | sed -E 's/@(cloudposse|community|testing)//g' ) && \ mkdir -p /etc/bash_completion.d/ /etc/profile.d/ # Install `tofu` as an alternative to `terraform`, if it is available. # Set priority to 5, which is lower than any other Cloud Posse Terraform package, # so that it is available, if Terraform is not installed, but does not interfere with Terraform installations. RUN command -v tofu >/dev/null && update-alternatives --install /usr/bin/terraform terraform $(command -v tofu) 5 # Here is where we would confirm that the package repo checksum is what we expect (not mismatched due to Docker layer cache) # Using the en_US.UTF-8 local breaks our login setup because it changes the sort order, # and therefore the order of execution, of our profile files. We use locale C.UTF-8 instead, # which is widely supported (more widely than en_US.UTF-8). However, if # we had a compelling reason to need en_US.UTF-8, we could install the # "locales" package and run the following command: # RUN localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 # Not sure why we were disabling IPv6, but we should not do that anymore, as IPv6 is stable and useful # RUN echo "net.ipv6.conf.all.disable_ipv6=0" > /etc/sysctl.d/00-ipv6.conf # Disable vim from reading a swapfile (incompatible with goofys) RUN echo 'set noswapfile' >> /etc/vim/vimrc WORKDIR /tmp # Copy the Rust binary from the Rust build stage COPY --from=rust /usr/local/bin/terminal-theme-detector /usr/local/bin/terminal-theme-detector # Copy python dependencies COPY --from=python /usr/local/ /usr/local/ # Explicitly set KUBECONFIG to enable kube_ps1 prompt ENV KUBECONFIG="${HOME}/.kube/config" # Install an empty kubeconfig to suppress some warnings COPY rootfs/etc/kubeconfig "${KUBECONFIG}" # Set mode on kubeconfig to suppress some warnings while installing tools RUN chmod 600 $KUBECONFIG # # Install kubectl # RUN kubectl completion bash > /etc/bash_completion.d/kubectl.sh # https://github.com/ahmetb/kubectx/releases ARG KUBECTX_COMPLETION_VERSION ADD https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_COMPLETION_VERSION}/completion/kubens.bash /etc/bash_completion.d/kubens.sh ADD https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_COMPLETION_VERSION}/completion/kubectx.bash /etc/bash_completion.d/kubectx.sh # # Install fancy Kube PS1 Prompt # https://github.com/jonmosco/kube-ps1/releases ARG KUBE_PS1_VERSION ADD https://raw.githubusercontent.com/jonmosco/kube-ps1/v${KUBE_PS1_VERSION}/kube-ps1.sh /etc/profile.d/prompt:kube-ps1.sh RUN chmod 755 /etc/bash_completion.d/kubens.sh /etc/bash_completion.d/kubectx.sh /etc/profile.d/prompt:kube-ps1.sh # # Install helm # ############# End of Helm 2 support ################################ # We no longer install helm2. If you want to install it yourself, copy and uncomment the following: # # # helm version 2 config # ENV HELM_HOME /var/lib/helm # ENV HELM_VALUES_PATH=${SECRETS_PATH}/helm/values # # RUN helm2 completion bash > /etc/bash_completion.d/helm2.sh \ # && mkdir -p ${HELM_HOME} \ # && helm2 init --client-only \ # && mkdir -p ${HELM_HOME}/plugins # # # Enable Atlantis to use helm 2 # RUN chmod -R a+rwX ${HELM_HOME} # # ARG HELM_HELM_2TO3_VERSION=0.10.0 # RUN helm3 plugin install https://github.com/helm/helm-2to3 --version ${HELM_HELM_2TO3_VERSION} # ############# End of Helm 2 support ################################ # # Install minimal helm plugins ARG HELM_DIFF_VERSION ARG HELM_GIT_VERSION RUN helm3 plugin install https://github.com/databus23/helm-diff.git --version v${HELM_DIFF_VERSION} \ && helm3 plugin install https://github.com/aslafy-z/helm-git.git --version ${HELM_GIT_VERSION} \ && rm -rf $XDG_CACHE_HOME/helm # helm version 3 uses XDG variables set above. # XDG directory permissions updated at end of installs. # See https://helm.sh/docs/faq/#xdg-base-directory-support # # Configure host AWS configuration to be available from inside Docker image # # AWS_DATA_PATH is a PATH-like variable for configuring the AWS botocore library to # load additional modules. Do not set it. ARG GEODESIC_AWS_HOME=${HOME}/.aws # Region abbreviation types are "fixed" (always 3 chars), "short" (4-5 chars), or "long" (the full AWS string) # See https://github.com/cloudposse/terraform-aws-utils#introduction ENV AWS_REGION_ABBREVIATION_TYPE=short # Shell customization # options for `less`. `R` allows ANSI color codes to be displayed while stripping out # other control codes that can cause `less` to mess up the screen formatting ENV LESS=R # MANOPT=--no-hyphenation disables hyphenation for man pages, which is generally preferable # for the man pages in Geodesic to preserve the ability to copy and paste code. ENV MANOPT=--no-hyphenation # Support for using an SSH key file on the host. No longer favored now that # Docker supports forwarding SSH_AUTH_SOCK, but retained for backward compatibility. # See rootfs/etc/profile.d/ssh-agent.sh ENV SSH_AGENT_CONFIG=/var/tmp/.ssh-agent # Install "root" filesystem # Debian, starting with v12 (bookworm), has symbolic links for /bin, /sbin, and /lib # so we cannot have those directories under rootfs and copy the whole directory. COPY rootfs/ / COPY os/debian/rootfs/ / # For certain pagkage we like to have but are not available on arm64, # install them on amd64, and link to a stub script on arm64. RUN if [ "$TARGETARCH" = "amd64" ]; then \ apt-get update && apt-get install -y \ $(grep -h -v '^#' /etc/apt/packages-amd64-only.txt | sed -E 's/@(cloudposse|community|testing)//g' ); \ else \ for pkg in $(grep -h -v '^#' /etc/apt/packages-amd64-only.txt | sed -E 's/@(cloudposse|community|testing)//g' ); do \ ln -s /usr/local/bin/no-arm64-support /usr/local/bin/$pkg; \ done; \ fi # Move AWS CLI v1 aside (if installed) and install AWS CLI v2 as default, leaving both available as alternatives. # We do this at the end because we need cache busting from above to get us the latest AWS CLI v2 RUN if [[ -x /usr/local/bin/aws ]]; then mv /usr/local/bin/aws /usr/local/bin/aws1 && \ mv /usr/local/bin/aws_completer /usr/local/bin/aws1_completer && \ update-alternatives --install /usr/local/bin/aws aws /usr/local/bin/aws1 1 \ --slave /usr/local/bin/aws_completer aws_completer /usr/local/bin/aws1_completer; \ fi # Install AWS CLI 2 # Get AWS CLI V2 version from https://github.com/aws/aws-cli/blob/v2/CHANGELOG.rst if you want # but it is updated several times a week, so we choose to just get the latest. # It is available in a Debian package `awscli`, but that can be very out of date. # ARG AWS_CLI_VERSION=2.15.48 RUN AWSTMPDIR=$(mktemp -d -t aws-inst-XXXXXXXXXX) && \ if [ "$TARGETARCH" = "amd64" ]; then \ AWS_ARCH=x86_64; else AWS_ARCH=aarch64; fi && \ curl -sSL "https://awscli.amazonaws.com/awscli-exe-linux-${AWS_ARCH}${AWS_CLI_VERSION:+-${AWS_CLI_VERSION}}.zip" -o "$AWSTMPDIR/awscliv2.zip" && \ savedir="$PWD" && cd $AWSTMPDIR && \ unzip -qq awscliv2.zip && \ ./aws/install -i /usr/share/aws/v2 -b /usr/share/aws/v2/bin && \ update-alternatives --install /usr/local/bin/aws aws /usr/share/aws/v2/bin/aws 2 \ --slave /usr/local/bin/aws_completer aws_completer /usr/share/aws/v2/bin/aws_completer && \ update-alternatives --set aws /usr/share/aws/v2/bin/aws && \ ln -s /usr/share/aws/v2/bin/aws /usr/local/bin/aws2 && \ ln -s /usr/share/aws/v2/bin/aws_completer /usr/local/bin/aws2_completer && \ cd "$savedir" && rm -rf $AWSTMPDIR # We recommend AWS_PAGER="less -FRX" but you can override it in your Dockerfile # or in your Geodesic preferences (see `man customization`). # FRX acts like it does not invoke the pager unless the output would be # more than can fit on one scree, while preserving text color/bold. # FRX is actually the AWS default, except we overrode the default above by setting ENV LESS. # options to `less`: # F = Quit if output fits on one screen, so short output remains visible after the command finishes # R = Output "raw" control characters, so that text treatment like "bold" text is retained as "bold" text rather than quoted escapes # X = Disable termcap init/de-init sequences, keeps the pager from clearing the screen when it finishes ENV AWS_PAGER="less -FRX" # Install AWS Session Manager Plugin ARG SESSION_MANAGER_PLUGIN_VERSION RUN if [ "$TARGETARCH" = "amd64" ]; then \ AWS_ARCH=64bit; else AWS_ARCH="$TARGETARCH"; fi && \ curl -sSL "https://s3.amazonaws.com/session-manager-downloads/plugin/${SESSION_MANAGER_PLUGIN_VERSION}/ubuntu_${AWS_ARCH}/session-manager-plugin.deb" \ -o "/tmp/session-manager-plugin.deb" && \ sudo dpkg -i /tmp/session-manager-plugin.deb && \ rm -f /tmp/session-manager-plugin.deb # This is a workaround for https://github.com/moby/buildkit/issues/5775 # CHAMBER_KMS_KEY_ALIAS is used by the `chamber` CLI, but it is incorrectly # flagged as a secret by the SecretsUsedInArgOrEnv check. This is a false positive. # So, as a workaround, we allow you to set `CHAMBER_KMS_ALIAS` instead, # and at runtime we copy the value to `CHAMBER_KMS_KEY_ALIAS` for you. ENV CHAMBER_KMS_ALIAS=aws/ssm # Install documentation COPY docs/ /usr/share/docs/ # Build man pages # `pandoc` is huge, so we only install it temporarily RUN apt-get update && apt-get install -y --no-install-recommends pandoc && \ /usr/local/bin/docs update; \ apt-get remove -y pandoc && apt-get autoremove -y # Make sure that "user specific" directories we are sharing # are in fact available to all users RUN for dir in $XDG_DATA_HOME $XDG_CONFIG_HOME $XDG_CACHE_HOME; do \ chmod -R a+rwX $dir; done RUN mkdir /workspace WORKDIR /workspace ENTRYPOINT ["/bin/bash"] CMD ["-c", "boot"] ARG DEV_VERSION ENV GEODESIC_DEV_VERSION=$DEV_VERSION ENV GEODESIC_VERSION="${GEODESIC_VERSION}${GEODESIC_DEV_VERSION:+ (${GEODESIC_DEV_VERSION})}"