Last active
April 5, 2022 09:19
-
-
Save metafeather/44461f814845eed3e0e6d567735209c1 to your computer and use it in GitHub Desktop.
Personal dev container
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Global args | |
ARG DEBIAN_VERSION="bullseye-slim" | |
ARG GOLANG_VERSION="1.17" | |
ARG NODE_VERSION="16" | |
ARG PYTHON_VERSION="3.10" | |
ARG RUBY_VERSION="3.1.0" | |
############################ | |
# Base images | |
############################ | |
FROM scratch AS base | |
FROM debian:${DEBIAN_VERSION} AS hostos | |
# ref: https://github.com/GoogleContainerTools/distroless | |
# FROM gcr.io/distroless/nodejs | |
FROM node:${NODE_VERSION}-bullseye-slim AS node | |
FROM python:${PYTHON_VERSION}-slim-bullseye AS python | |
FROM golang:${GOLANG_VERSION}-bullseye AS golang | |
FROM ruby:${RUBY_VERSION}-slim-bullseye AS ruby | |
############################ | |
# Runtime IDE | |
############################ | |
# ref: https://github.com/ls12styler/ide/blob/master/Dockerfile | |
# ref: https://github.com/JAremko/drop-in/blob/master/Dockerfile | |
# ref: https://medium.com/@ls12styler/docker-as-an-integrated-development-environment-95bc9b01d2c1 | |
# ref: https://medium.com/rate-engineering/using-docker-containers-as-development-machines-4de8199fc662 | |
# ref: https://gitlab.com/ESC/containers/-/blob/master/Docker/utilities/dsh/dsh | |
# ref: https://jtreminio.com/blog/running-docker-containers-as-current-host-user/#ok-so-what-actually-works | |
FROM hostos AS runtime | |
USER root | |
WORKDIR /tmp | |
# Change to force rebuild of all layers | |
RUN echo "runtime: 2022-03-21.1" | |
# Set Timezone for tzdata | |
ENV TZ=Europe/London | |
# Get security updates | |
RUN apt-get update --yes | |
RUN apt-get upgrade --yes | |
# install - packages.txt | |
COPY packages.txt /tmp/packages.txt | |
ENV DEBIAN_FRONTEND=noninteractive | |
RUN apt-get update --yes \ | |
&& apt-get install --yes --no-install-recommends $(grep -o ^[^#]* /tmp/packages.txt) \ | |
&& apt-get clean \ | |
&& rm -rf /var/lib/apt/lists/* | |
# Extra distributions | |
RUN curl -fsSL 'https://download.docker.com/linux/debian/gpg' | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg | |
RUN echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list | |
RUN apt-get update --yes | |
RUN apt-get install -y --no-install-recommends \ | |
docker-ce-cli | |
# Cleanup apt lists | |
RUN apt-get clean && rm -rf /var/lib/apt/lists/* | |
# Bugfixes | |
# ref: https://github.com/sudo-project/sudo/issues/42 | |
RUN echo "Set disable_coredump false" >> /etc/sudo.conf | |
############################ | |
# Developer runtime | |
############################ | |
FROM runtime AS developer | |
USER root | |
# ref: https://vsupalov.com/docker-arg-env-variable-guide/ | |
# Build args - defaults based on Amazon EC2 | |
ARG HOST_OS="Linux" | |
ARG HOST_HOSTNAME="user" | |
ARG HOST_USER="user" | |
ARG HOST_USER_UID=1000 | |
ARG HOST_USER_GID=${HOST_USER_UID} | |
ARG HOST_HOME="/home/${HOST_USER}" | |
ARG HOST_COLOR="" | |
ARG PROJECT_NAME="user" | |
ARG PROJECT_HOME="${HOST_HOME}/opt/${PROJECT_NAME}" | |
ARG PROJECT_COLOR="" | |
# Share build args in env | |
ENV HOST_OS ${HOST_OS} | |
ENV HOST_HOSTNAME ${HOST_HOSTNAME} | |
ENV HOST_USER ${HOST_USER} | |
ENV HOST_USER_UID ${HOST_USER_UID} | |
ENV HOST_USER_GID ${HOST_USER_GID} | |
ENV HOST_HOME ${HOST_HOME} | |
ENV HOST_COLOR ${HOST_COLOR} | |
ENV PROJECT_NAME ${PROJECT_NAME} | |
ENV PROJECT_COLOR ${PROJECT_COLOR} | |
# Duplicates host user as UID/GID=1000 and adds to groups | |
# ref: https://wiki.alpinelinux.org/wiki/Setting_up_a_new_user | |
# ref: docker run alpine sh -c 'apk add shadow sudo && useradd' | |
RUN groupadd \ | |
--force \ | |
--gid ${HOST_USER_GID} \ | |
--non-unique \ | |
${HOST_USER} | |
# Mount /home/code/user as $HOME for mapped host user | |
RUN useradd \ | |
--comment 'Added by Dockerfile' \ | |
--home-dir ${PROJECT_HOME} \ | |
--gid ${HOST_USER_GID} \ | |
--create-home \ | |
--non-unique \ | |
--shell /bin/zsh \ | |
--uid ${HOST_USER_UID} \ | |
${HOST_USER} | |
RUN chown -R ${HOST_USER_UID}:${HOST_USER_GID} ${PROJECT_HOME} | |
# Passwordless sudo | |
RUN echo ${HOST_USER} ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/${HOST_USER} \ | |
&& chmod 0440 /etc/sudoers.d/${HOST_USER} | |
# give permission to access host docker via bind mount /var/run/docker.sock | |
RUN groupadd docker | |
RUN addgroup ${HOST_USER} docker | |
############################ | |
# Build/download binary utils | |
############################ | |
# ref: https://weberc2.bitbucket.io/posts/golang-docker-scratch-app.html | |
FROM golang AS binaries | |
USER root | |
# Set Timezone for tzdata | |
ENV TZ=Europe/London | |
# Get security updates | |
RUN apt-get update --yes | |
RUN apt-get upgrade --yes | |
# Install git + SSL CA certificates. | |
# Git is required for fetching the dependencies. | |
# CA-certificates is required to call HTTPS endpoints. | |
RUN apt-get install --yes --no-install-recommends \ | |
git ca-certificates tzdata \ | |
curl | |
RUN update-ca-certificates | |
WORKDIR /opt/bin | |
ENV PATH="/opt/bin:${PATH}" | |
# Debug Docker build env | |
RUN go env | |
# Build binaries with CGO_ENABLED=0 so we use the pure-Go implementations for | |
# things like DNS resolution (so we don't depend on system libraries) | |
#RUN go get github.com/ochinchina/supervisord | |
#RUN env CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -installsuffix cgo -o ./bin/supervisord github.com/ochinchina/supervisord | |
# TODO: build tmux | |
############################ | |
# User image | |
############################ | |
FROM developer as user | |
# User can install binaries | |
RUN chgrp ${HOST_USER} /usr/local/bin && chmod g+w /usr/local/bin | |
# Run as nonroot user to match the host | |
ENV USER ${HOST_USER} | |
ENV HOME ${PROJECT_HOME} | |
USER ${USER} | |
WORKDIR ${HOME} | |
# Uses SSH auth socket location set in .bash_aliases on host SSH login | |
# and mounted into Docker so agent forwarding works with tmux and in containers | |
# ref: https://blog.testdouble.com/posts/2016-11-18-reconciling-tmux-and-ssh-agent-forwarding/ | |
ENV SSH_AUTH_SOCK "/tmp/tmux_ssh-agent.sock" | |
# Copy standalone binaries | |
COPY --chown=${USER} --from=binaries /opt/bin/ /opt/bin/ | |
ENV PATH="/opt/bin:${PATH}" | |
RUN mkdir -p ~/.cache/bin | |
ENV PATH=~/.cache/bin:${PATH} | |
# Create build time dirs and symlinks | |
# Can be overridden by volume mounts | |
RUN mkdir -p \ | |
/tmp/.vscode-server | |
RUN ln -sf /tmp/.vscode-server ~/ | |
# Gather expected build time configs | |
COPY --chown=${USER} entrypoint*.sh ./ | |
RUN chmod +x entrypoint*.sh | |
# Run entrypoint, can be overridden | |
WORKDIR ${HOME} | |
ENTRYPOINT ["./entrypoint.sh"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
cd ${HOME} | |
echo "Docker image ready for shell access." | |
# own $HOME mounts | |
sudo chown ${USER}: ${HOME}/.* | |
sudo chown ${USER}: ${HOME}/* | |
# give permission to access host docker via bind mount /var/run/docker.sock | |
# sudo chown root:docker /var/run/docker.sock | |
sudo touch /var/run/docker.sock | |
# create group matching host os docker gid | |
sudo groupadd --system --force --gid $(stat -c %g /var/run/docker.sock) --non-unique docker_host | |
sudo addgroup $USER docker_host | |
sudo chmod g+w /var/run/docker.sock | |
# ensure new group is used but not primary and run keepalive | |
# commands in subshells with expected groups | |
# ref: https://unix.stackexchange.com/questions/18897/problem-while-running-newgrp-command-in-script | |
newgrp docker_host <<SUB1 | |
newgrp $USER <<SUB2 | |
# Enable direnv | |
direnv allow | |
export PROJECT_NAME="${PROJECT_NAME:-'user'}" | |
# Keepalive via tmux session | |
# while true | |
# do | |
# if [[ "$(tmux ls 2>$1)" != *""${PROJECT_NAME}""* ]]; then | |
# tmux new \ | |
# -s "${PROJECT_NAME}" \ | |
# -c "${HOME}" \ | |
# -n "~" \ | |
# -d | |
# echo "Started missing '${PROJECT_NAME}' tmux session" | |
# fi | |
# sleep 5 | |
# done | |
# Keepalive | |
while :; # Run an endless loop, | |
do :; # of do nothing, | |
done & # as background task. | |
kill -STOP $! # Stop the background task. | |
wait $! # Wait forever, because background task process has been stopped. | |
SUB2 | |
SUB1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# TODO: make devcontainer | |
# ref: https://code.visualstudio.com/docs/remote/create-dev-container | |
# ref: https://benmatselby.dev/post/vscode-dev-containers/ | |
# see also: https://code.visualstudio.com/docs/remote/devcontainerjson-reference | |
.DEFAULT_GOAL: help | |
ORG ?= $(shell hostname -s | tr A-Z a-z) | |
NAME ?= user.$(ORG) | |
VERSION ?= $(NAME):$(shell git rev-parse HEAD) | |
LATEST ?= $(NAME):latest | |
############################ | |
# Utils | |
############################ | |
# callable with args, e.g. $(call help, Some text) | |
log = @(printf "\033[32m>> $1\n\033[39m") | |
# Dynamic help generated from usage vars | |
.PHONY: help | |
help: usage := Show usage messages | |
help: usage | |
help: | |
@grep -E '^[a-zA-Z_-]+:.*?usage := .*$$' Makefile | sort | awk 'BEGIN {FS = ":.*?usage := "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' | |
.PHONY: usage | |
usage: | |
$(call log, $(usage)) | |
############################ | |
# Targets | |
############################ | |
.PHONY: down | |
down: usage := Stop the docker image | |
down: usage | |
down: | |
@docker rm -f $(NAME) || true | |
EXTRA_DOCKER_RUN_ARGS ?= -p 9000-9019:9000-9019 | |
# --mount type=bind,src=$(shell readlink -f "/tmp/tmux_ssh-agent.sock"),dst=/tmp/tmux_ssh-agent.sock | |
.PHONY: up | |
up: usage := Start the docker image | |
up: usage | |
up: HOST_HOSTNAME ?= $(NAME).docker | |
up: HOST_HOME ?= $(HOME) | |
up: HOST_COLOR ?= cdf632 | |
up: PROJECT_COLOR ?= f8961e | |
up: | |
@docker run -dt --restart unless-stopped \ | |
--add-host=host.docker.internal:host-gateway \ | |
--name $(NAME) \ | |
-h $(HOST_HOSTNAME) \ | |
--log-opt max-size=10m --log-opt max-file=5 \ | |
--env HOST_COLOR=$(HOST_COLOR) \ | |
--env PROJECT_COLOR=$(PROJECT_COLOR) \ | |
--mount source=$(NAME).vscode-server,target=/tmp/.vscode-server \ | |
--mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \ | |
--mount type=bind,src=$(HOST_HOME)/opt,dst=$(HOST_HOME)/opt \ | |
--mount type=bind,src=$(HOST_HOME)/.ssh,dst=$(HOST_HOME)/opt/user/.ssh \ | |
--env SSH_AUTH_SOCK=$(HOST_HOME)/opt/user/.ssh/agent.sock \ | |
$(EXTRA_DOCKER_RUN_ARGS) \ | |
$(LATEST) | |
.PHONY: logs | |
logs: usage := View realtime logs of the running docker image | |
logs: usage | |
logs: | |
@docker logs -f $(NAME) | |
.PHONY: shell | |
shell: usage := Attach a shell to the running docker image | |
shell: usage | |
shell: | |
@docker exec -it $(NAME) /bin/zsh | |
### Deployments | |
.PHONY: build | |
build: usage := Build the docker image | |
build: usage | |
build: HOST_OS ?= $(shell uname -s) | |
build: HOST_HOSTNAME ?= $(NAME).docker | |
build: HOST_USER ?= $(USER) | |
build: HOST_USER_UID ?= $(shell id -u) | |
build: HOST_USER_GID ?= $(shell id -g) | |
build: HOST_HOME ?= $(HOME) | |
build: | |
@DOCKER_BUILDKIT=1 docker build --rm -f Dockerfile \ | |
--build-arg HOST_OS=$(HOST_OS) \ | |
--build-arg HOST_HOSTNAME=$(HOST_HOSTNAME) \ | |
--build-arg HOST_USER=$(HOST_USER) \ | |
--build-arg HOST_USER_UID=$(HOST_USER_UID) \ | |
--build-arg HOST_HOME=$(HOST_HOME) \ | |
--target user \ | |
-t $(LATEST) . | |
.PHONY: user | |
user: usage := User: default | |
user: build down up |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Allow adding repos | |
apt-transport-https | |
ca-certificates | |
debian-keyring | |
debian-archive-keyring | |
gnupg2 | |
software-properties-common | |
# Basic utils | |
mandoc | |
mime-support | |
util-linux | |
xdg-utils | |
procps | |
# Common build libs | |
bzip2 | |
clang | |
gcc | |
libssl-dev | |
make | |
zlib1g-dev | |
# Common network access | |
netcat # Used to connect to host vscode | |
openssh-client | |
socat | |
# Common tools | |
bash # for tmux + tpm to work | |
bash-completion | |
curl | |
git | |
less | |
rsync | |
sed | |
sudo | |
tmux | |
unzip | |
wget | |
zsh | |
# User tools | |
hstr | |
htop | |
postgresql-client |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment