Skip to content

Instantly share code, notes, and snippets.

@stonier
Created February 6, 2024 20:15
Show Gist options
  • Save stonier/e9edd298308a2554d447d2a3dcca8c5e to your computer and use it in GitHub Desktop.
Save stonier/e9edd298308a2554d447d2a3dcca8c5e to your computer and use it in GitHub Desktop.
Borg Dockerfile
################################################################################
# Base
# - a borg image containing all the dependencies for simulation tooling.
# Does the following:
# - The image is based off a parameter containing the ubuntu version.
# - Installs base deb requirements (DEBS_DEVEL).
# - Adds a user called 'zen' and adds this users to the sudoers group.
# - Adds login shells for debugging & development.
# - Installs Rust toolchain for specified rust version (RUST_VERSION).
# - Installs Rust autocompletion for bash.
# - Installs Bazelisk (BAZELISK_VERSION) and Bazel (BAZEL_VERSION).
# - Installs Buildifier (BUILDIFIER_VERSION).
# - Installs PyEnv (PYENV__VERSION - note the double underscore).
# - Installs Python3 via pyenv (PYTHON_PRIMARY_VERSION, PYTHON_SECONDARY_VERSION).
# - Installs Poetry (POETRY_VERSION).
# - Installs protoc (PROTOC_PRIMARY_VERSION and PROTOC_VERSION).
# - Installs protomgr (PROTOMGR_VERSION).
################################################################################
# Pass in ARGS via values from DEPENDENCIES
ARG UBUNTU_VERSION=
FROM ubuntu:${UBUNTU_VERSION}
# Repeated, because FROM will wipe all args before it.
ARG UBUNTU_VERSION=
ARG NAME=borg
ARG DEBS_DEVEL=
# Use bash for all commands.
SHELL ["/bin/bash", "-c"]
################################################################################
# Installs base deb requirements (DEBS_DEVEL).
################################################################################
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get install -y --no-install-recommends ${DEBS_DEVEL} \
&& apt-get autoremove \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
################################################################################
# Adds a user called 'zen' and adds this users to the sudoers group.
################################################################################
# Create a user.
ARG USERNAME=zen
ARG USER_UID=1000
ARG USER_GID=${USER_UID}
RUN groupadd --gid $USER_GID $USERNAME && \
useradd --uid $USER_UID --gid $USER_GID -s "/bin/bash" -m $USERNAME && \
echo "${USERNAME} ALL=NOPASSWD: ALL" > /etc/sudoers.d/${USERNAME} && \
chmod 0440 /etc/sudoers.d/${USERNAME}
RUN echo "export PS1='\[\033[01;36m\](docker)\[\033[00m\] \[\033[01;32m\]\u@${NAME}\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '" >> /home/${USERNAME}/.bashrc && \
echo "alias ll='ls --color=auto -alFNh'" >> /home/${USERNAME}/.bashrc && \
echo "alias ls='ls --color=auto -Nh'" >> /home/${USERNAME}/.bashrc
RUN mkdir -p /home/${USERNAME}/.local/share/bash-completion/completions/ && \
chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}/.local
# Debugging with root.
RUN echo "export PS1='\[\033[01;36m\](docker)\[\033[00m\] \[\033[01;32m\]\u@${NAME}\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '" >> ${HOME}/.bashrc && \
echo "alias ll='ls --color=auto -alFNh'" >> ${HOME}/.bashrc && \
echo "alias ls='ls --color=auto -Nh'" >> ${HOME}/.bashrc
################################################################################
# Adds login shells for debugging & development.
################################################################################
ENV TERM xterm-256color
ENTRYPOINT ["/bin/bash", "--login", "-i"]
# When running the container, pyenv and poetry complain with weird issues like:
# LC_CTYPE: cannot change locale (UTF-8): No such file or directory
# This seems to fix it.
ENV LANG="C.UTF-8"
ENV LANGUAGE="C.UTF-8"
ENV LC_ALL="C.UTF-8"
RUN echo 'export LANG="C.UTF-8"' >> /etc/profile && \
echo 'LANGUAGE="C.UTF-8"' >> /etc/profile && \
echo 'LC_ALL="C.UTF-8"' >> /etc/profile
################################################################################
# Installs Rust toolchain for specified rust version (RUST_VERSION).
# Installs Rust autocompletion for bash.
################################################################################
ARG RUST_VERSION=
ENV RUSTUP_HOME="/opt/rustup"
ENV CARGO_HOME="/opt/cargo"
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain ${RUST_VERSION} \
&& source "${CARGO_HOME}/env" \
&& rustup component add clippy \
&& rustup component add rustfmt \
&& cargo install binstall \
&& cargo install cargo-deb \
&& cargo install cargo-expand \
&& cargo install cargo-rdme \
&& cargo install mdbook \
&& rustup target add x86_64-unknown-linux-musl \
&& rustup completions bash cargo >> /home/${USERNAME}/.local/share/bash-completion/completions/cargo \
&& echo "export RUSTUP_HOME=${RUSTUP_HOME}" >> /etc/profile \
&& echo "export PATH=${CARGO_HOME}/bin:\${PATH}" >> /etc/profile
ENV PATH="$CARGO_HOME/bin/:$PATH"
# The previous command roots permissions in ${CARGO_HOME} and ${RUSTUP_HOME}.
# Establish wide permissions for user 'zen'. This step takes several minutes.
RUN find ${CARGO_HOME} -type d -exec chmod 777 {} + && \
find ${CARGO_HOME} -type f -exec chmod a+rw {} + && \
find ${RUSTUP_HOME} -type d -exec chmod 777 {} + && \
find ${RUSTUP_HOME} -type f -exec chmod a+rw {} +
################################################################################
# Installs Bazelisk (BAZELISK_VERSION) and Bazel (BAZEL_VERSION)
################################################################################
# Be specific about an architecture so that we can build an arm image as well.
ARG BAZELISK_HOME=/opt/bazelisk/bin
ARG BAZELISK_VERSION=
# Use amd64 by default
ARG TARGET_ARCH=amd64
# 6.4.0 is the latest as of Oct 31, 2023. Belated Happy Halloween!
ARG BAZEL_VERSION=6.4.0
# This environment variable tells bazelisk which bazel version to pull by default.
ENV USE_BAZEL_VERSION=${BAZEL_VERSION}
RUN mkdir -p ${BAZELISK_HOME} && \
chmod 777 ${BAZELISK_HOME} && \
# Install bazelisk as bazel itself.
wget https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK_VERSION}/bazelisk-linux-${TARGET_ARCH} -O ${BAZELISK_HOME}/bazel && \
chmod +x ${BAZELISK_HOME}/bazel && \
echo "export PATH=${BAZELISK_HOME}:\${PATH}" >> /etc/profile
################################################################################
# Installs Buildifier (BUILDIFIER_VERSION).
################################################################################
ARG BUILDIFIER_VERSION=
ARG BUILDIFIER_HOME=/opt/buildifier/bin
RUN mkdir -p ${BUILDIFIER_HOME} && \
chmod 777 ${BUILDIFIER_HOME} && \
wget https://github.com/bazelbuild/buildtools/releases/download/v${BUILDIFIER_VERSION}/buildifier-linux-${TARGET_ARCH} -O ${BUILDIFIER_HOME}/buildifier && \
chmod +x ${BUILDIFIER_HOME}/buildifier && \
echo "export PATH=${BUILDIFIER_HOME}:\${PATH}" >> /etc/profile
################################################################################
# Installs PyEnv (PYENV__VERSION - note the double underscore).
################################################################################
# Don't use PYENV_VERSION since PYENV uses that as a variable to determine
# the version of python to use.
ARG PYENV__VERSION=
ENV PYENV_GIT_TAG=v${PYENV__VERSION}
ENV PYENV_ROOT=/opt/pyenv
ENV PATH="${PYENV_ROOT}/shims:$PYENV_ROOT/bin:$PATH"
RUN curl https://pyenv.run | bash && \
echo 'export PYENV_ROOT="$PYENV_ROOT"' >> /etc/profile && \
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> /etc/profile && \
echo 'eval "$(pyenv init -)"' >> /etc/profile && \
# This should work whether you use bash -l or bash since devcontainers
# won't log you in.
echo 'export PYENV_ROOT="$PYENV_ROOT"' >> /etc/bash.bashrc && \
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> /etc/bash.bashrc && \
echo 'eval "$(pyenv init -)"' >> /etc/bash.bashrc
################################################################################
# Installs Python3 via pyenv (PYTHON_PRIMARY_VERSION, PYTHON_SECONDARY_VERSION).
################################################################################
ARG PYTHON_PRIMARY_VERSION
ARG PYTHON_SECONDARY_VERSION
RUN source /etc/profile && \
pyenv install ${PYTHON_PRIMARY_VERSION} && \
pyenv install ${PYTHON_SECONDARY_VERSION} && \
pyenv global ${PYTHON_PRIMARY_VERSION} && \
# Setup permissions for pyenv so all users can run it.
chmod -R 777 ${PYENV_ROOT} && \
source /etc/profile && \
mkdir -p ${PYENV_ROOT}/shims/ && \
chmod -R 777 ${PYENV_ROOT}/shims/ && \
mkdir -p ${PYENV_ROOT}/versions/ && \
chmod -R 777 ${PYENV_ROOT}/versions/
################################################################################
# Installs Poetry (POETRY_VERSION).
################################################################################
ARG POETRY_VERSION=
ARG POETRY_HOME=/opt/poetry
ENV POETRY_VERSION=${POETRY_VERSION}
ENV POETRY_HOME=${POETRY_HOME}
ENV PATH="$POETRY_HOME/bin/:$PATH"
RUN unset PYENV_VERSION && \
curl -sSL https://install.python-poetry.org | python3 - && \
echo "export PATH=${POETRY_HOME}/bin:\${PATH}" >> /etc/profile && \
poetry config virtualenvs.create false
################################################################################
# Installs protoc (PROTOC_PRIMARY_VERSION and PROTOC_VERSION).
################################################################################
ARG PROTOC_PRIMARY_VERSION=
ARG PROTOC_SECONDARY_VERSION=
# You can use the PROTOC_ARCH variable in subsequent commands or as needed
ARG PROTOC_ARCH=x86_64
# Primary (Added to Path)
ENV PROTOC_VERSION=${PROTOC_PRIMARY_VERSION}
ENV PROTOC_PATH_DIR=/opt/protoc-${PROTOC_VERSION}/bin/
ENV PROTOC=${PROTOC_PATH_DIR}/protoc
RUN wget https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-${PROTOC_ARCH}.zip -O /tmp/protoc.zip \
&& mkdir /opt/protoc-${PROTOC_VERSION} \
&& unzip /tmp/protoc.zip -d /opt/protoc-${PROTOC_VERSION} \
&& chown -R root:root /opt/protoc-${PROTOC_VERSION} \
&& find /opt/protoc-${PROTOC_VERSION} -type d -exec chmod 755 {} + \
&& find /opt/protoc-${PROTOC_VERSION} -type f -exec chmod 644 {} + \
&& chmod 777 ${PROTOC} \
&& chmod +x ${PROTOC} \
&& echo "export PATH=${PROTOC_PATH_DIR}:\${PATH}" >> /etc/profile \
&& rm /tmp/protoc.zip
# Secondary (Not added to PATH)
ENV PROTOC_VERSION=${PROTOC_SECONDARY_VERSION}
ENV PROTOC_PATH_DIR=/opt/protoc-${PROTOC_VERSION}/bin/
ENV PROTOC=${PROTOC_PATH_DIR}/protoc
RUN wget https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-${PROTOC_ARCH}.zip -O /tmp/protoc.zip \
&& mkdir /opt/protoc-${PROTOC_VERSION} \
&& unzip /tmp/protoc.zip -d /opt/protoc-${PROTOC_VERSION} \
&& chown -R root:root /opt/protoc-${PROTOC_VERSION} \
&& find /opt/protoc-${PROTOC_VERSION} -type d -exec chmod 755 {} + \
&& find /opt/protoc-${PROTOC_VERSION} -type f -exec chmod 644 {} + \
&& chmod 777 ${PROTOC} \
&& chmod +x ${PROTOC} \
&& rm /tmp/protoc.zip
################################################################################
# Installs protomgr (PROTOMGR_VERSION).
################################################################################
# Install Protomgr via PIPX.
ENV PIPX_HOME=/opt/pipx
ENV PIPX_BIN_DIR=/usr/local/bin
RUN mkdir -p ${PIPX_BIN_DIR} ${PIPX_HOME} && chmod 777 ${PIPX_BIN_DIR} ${PIPX_HOME}
# This value is set in DEPENDENCIES.
ARG PIPX_VERSION
RUN python3 -m pip install --user --disable-pip-version-check --no-cache-dir pipx==${PIPX_VERSION} && \
python3 -m pipx ensurepath && \
source ~/.bashrc
# This value is set in DEPENDENCIES.
ARG PROTOMGR_VERSION
ARG PRE_COMMIT_VERSION
RUN --mount=type=secret,id=NETRC,target=/root/.netrc,required=true,mode=444 \
python3 -m pip config set global.trusted-host "artifactory-ha.tmc-stargate.com pypi.org" && \
python3 -m pip config set global.index https://artifactory-ha.tmc-stargate.com:443/artifactory/api/pypi/arene-driving-pypi-local-internal/ && \
python3 -m pip config set global.index-url https://artifactory-ha.tmc-stargate.com:443/artifactory/api/pypi/arene-driving-pypi-local-internal/simple/ && \
python3 -m pip config set global.extra-index-url https://pypi.org/simple/ && \
python3 -m pipx install protomgr==${PROTOMGR_VERSION} && \
python3 -m pipx install pre-commit==${PRE_COMMIT_VERSION}
################################################################################
# Installs flatc (FLATC_VERSION).
################################################################################
# This value is set in DEPENDENCIES.
ARG FLATC_VERSION
RUN wget https://github.com/google/flatbuffers/releases/download/v${FLATC_VERSION}/Linux.flatc.binary.clang++-12.zip && \
unzip Linux.flatc.binary.clang++-12.zip -d /usr/local/bin
################################################################################
# Variable reflection
################################################################################
# Add labels and ENV for identification
LABEL BAZEL_VERSION=$BAZEL_VERSION \
BAZELISK_VERSION=$BAZELISK_VERSION \
BUILDIFIER_VERSION=$BUILDIFIER_VERSION \
DEBS_DEVEL=$DEBS_DEVEL \
PIPX_VERSION=$PIPX_VERSION \
POETRY_VERSION=$POETRY_VERSION \
PRE_COMMIT_VERSION=$PRE_COMMIT_VERSION \
PROTOC_PRIMARY_VERSION=$PROTOC_PRIMARY_VERSION \
PROTOC_SECONDARY_VERSION=$PROTOC_SECONDARY_VERSION \
PROTOMGR_VERSION=$PROTOMGR_VERSION \
FLATC_VERSION=$FLATC_VERSION \
PYENV_VERSION=$PYENV__VERSION \
PYTHON_PRIMARY_VERSION=$PYTHON_PRIMARY_VERSION \
PYTHON_SECONDARY_VERSION=$PYTHON_SECONDARY_VERSION \
RUST_VERSION=$RUST_VERSION \
UBUNTU_VERSION=$UBUNTU_VERSION
ENV ZEN_BAZEL_VERSION=$BAZEL_VERSION \
ZEN_BAZELISK_VERSION=$BAZELISK_VERSION \
ZEN_BUILDIFIER_VERSION=$BUILDIFIER_VERSION \
ZEN_DEBS_DEVEL=$DEBS_DEVEL \
ZEN_PIPX_VERSION=$PIPX_VERSION \
ZEN_POETRY_VERSION=$POETRY_VERSION \
ZEN_PRE_COMMIT_VERSION=$PRE_COMMIT_VERSION \
ZEN_PROTOC_PRIMARY_VERSION=$PROTOC_PRIMARY_VERSION \
ZEN_PROTOC_SECONDARY_VERSION=$PROTOC_SECONDARY_VERSION \
ZEN_PROTOMGR_VERSION=$PROTOMGR_VERSION \
ZEN_FLATC_VERSION=$FLATC_VERSION \
ZEN_PYENV_VERSION=$PYENV__VERSION \
ZEN_PYTHON_PRIMARY_VERSION=$PYTHON_PRIMARY_VERSION \
ZEN_PYTHON_SECONDARY_VERSION=$PYTHON_SECONDARY_VERSION \
ZEN_RUST_VERSION=$RUST_VERSION \
ZEN_UBUNTU_VERSION=$UBUNTU_VERSION
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment