Skip to content
This repository has been archived by the owner on Nov 17, 2023. It is now read-only.

Add Codespaces support #1500

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Note: You can use any Debian/Ubuntu based image you want.
#FROM mcr.microsoft.com/vscode/devcontainers/base:0-buster
ARG VARIANT=3.1
FROM mcr.microsoft.com/vscode/devcontainers/dotnetcore:${VARIANT}

# Options
ARG INSTALL_ZSH="true"
ARG UPGRADE_PACKAGES="false"
ARG ENABLE_NONROOT_DOCKER="true"
ARG SOURCE_SOCKET=/var/run/docker-host.sock
ARG TARGET_SOCKET=/var/run/docker.sock
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID

# Install needed packages and setup non-root user. Use a separate RUN statement to add your own dependencies.
COPY library-scripts/*.sh /tmp/library-scripts/
RUN apt-get update \
&& /bin/bash /tmp/library-scripts/common-debian.sh "${INSTALL_ZSH}" "${USERNAME}" "${USER_UID}" "${USER_GID}" "${UPGRADE_PACKAGES}" \
# Use Docker script from script library to set things up
&& /bin/bash /tmp/library-scripts/docker-debian.sh "${ENABLE_NONROOT_DOCKER}" "${SOURCE_SOCKET}" "${TARGET_SOCKET}" "${USERNAME}" \
# Install Dapr
&& wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O - | /bin/bash \
# Clean up
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts/

# Install kubectl
RUN curl -sSL -o /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl \
&& chmod +x /usr/local/bin/kubectl

# Install Helm
RUN curl -s https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash -

# Script copies localhost's ~/.kube/config file into the container and swaps out
# localhost for host.docker.internal on bash/zsh start to keep them in sync.
COPY copy-kube-config.sh /usr/local/share/
RUN chown ${USERNAME}:root /usr/local/share/copy-kube-config.sh \
&& echo "source /usr/local/share/copy-kube-config.sh" | tee -a /root/.bashrc /root/.zshrc /home/${USERNAME}/.bashrc >> /home/${USERNAME}/.zshrc

# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>

# Setting the ENTRYPOINT to docker-init.sh will configure non-root access to the Docker
# socket. The script will also execute CMD if you need to alter startup behaviors.
ENTRYPOINT [ "/usr/local/share/docker-init.sh" ]
CMD [ "sleep", "infinity" ]
31 changes: 31 additions & 0 deletions .devcontainer/copy-kube-config.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash -i

# Copies localhost's ~/.kube/config file into the container and swap out localhost
# for host.docker.internal whenever a new shell starts to keep them in sync.
if [ "$SYNC_LOCALHOST_KUBECONFIG" = "true" ] && [ -d "/usr/local/share/kube-localhost" ]; then
mkdir -p $HOME/.kube
sudo cp -r /usr/local/share/kube-localhost/* $HOME/.kube
sudo chown -R $(id -u) $HOME/.kube
sed -i -e "s/localhost/host.docker.internal/g" $HOME/.kube/config
sed -i -e "s/127.0.0.1/host.docker.internal/g" $HOME/.kube/config

# If .minikube was mounted, set up client cert/key
if [ -d "/usr/local/share/minikube-localhost" ]; then
mkdir -p $HOME/.minikube
sudo cp -r /usr/local/share/minikube-localhost/ca.crt $HOME/.minikube
# Location varies between versions of minikube
if [ -f "/usr/local/share/minikube-localhost/client.crt" ]; then
sudo cp -r /usr/local/share/minikube-localhost/client.crt $HOME/.minikube
sudo cp -r /usr/local/share/minikube-localhost/client.key $HOME/.minikube
elif [ -f "/usr/local/share/minikube-localhost/profiles/minikube/client.crt" ]; then
sudo cp -r /usr/local/share/minikube-localhost/profiles/minikube/client.crt $HOME/.minikube
sudo cp -r /usr/local/share/minikube-localhost/profiles/minikube/client.key $HOME/.minikube
fi
sudo chown -R $(id -u) $HOME/.minikube

# Point .kube/config to the correct locaiton of the certs
sed -i -r "s|(\s*certificate-authority:\s).*|\\1$HOME\/.minikube\/ca.crt|g" $HOME/.kube/config
sed -i -r "s|(\s*client-certificate:\s).*|\\1$HOME\/.minikube\/client.crt|g" $HOME/.kube/config
sed -i -r "s|(\s*client-key:\s).*|\\1$HOME\/.minikube\/client.key|g" $HOME/.kube/config
fi
fi
58 changes: 58 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//////
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.134.1/containers/docker-from-docker-compose
{
"name": "Docker from Docker Compose + Kubernetes & Helm",
"dockerFile": "Dockerfile",

//"service": "docker-from-docker",
"workspaceFolder": "/workspace",

// Use this environment variable if you need to bind mount your local source code into a new container.
"remoteEnv": {
"LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}",
"SYNC_LOCALHOST_KUBECONFIG": "true"
},

"mounts": [
"source=/var/run/docker.sock,target=/var/run/docker-host.sock,type=bind",
"source=${env:HOME}${env:USERPROFILE}/.kube,target=/usr/local/share/kube-localhost,type=bind"
// Uncomment the next line to also sync certs in your .minikube folder
// "source=${env:HOME}${env:USERPROFILE}/.minikube,target=/usr/local/share/minikube-localhost,type=bind"
],

// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},

// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-azuretools.vscode-docker",
"ms-dotnettools.csharp",
"github.github-vscode-theme",
"coenraads.bracket-pair-colorizer-2",
"github.vscode-pull-request-github",
"ms-azuretools.vscode-docker",
"ms-vsliveshare.vsliveshare",
"vscode-icons-team.vscode-icons",
"visualstudioexptteam.vscodeintellicode",
"ms-azuretools.vscode-docker",
"ms-kubernetes-tools.vscode-kubernetes-tools",
"ms-mssql.mssql",
"formulahendry.dotnet-test-explorer"
],

// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "wget https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube-linux-amd64 && sudo mv minikube-linux-amd64 /usr/local/bin/minikube && minikube version"

// Uncomment when using a ptrace-based debugger like C++, Go, and Rust.
// "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],

// Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
// "overrideCommand": false,
//"remoteUser": "vscode"
}
32 changes: 32 additions & 0 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
version: '3'
services:
docker-from-docker:
# Uncomment the next line to use a non-root user for all processes.
# See https://aka.ms/vscode-remote/containers/non-root for details.
# user: vscode

build:
context: .
dockerfile: Dockerfile
args:
# On Linux, you may need to update USER_UID and USER_GID below if not your local UID is not 1000.
USER_UID: 1000
USER_GID: 1000

volumes:
# Update this to wherever you want VS Code to mount the folder of your project
- ..:/workspace:cached

# Forwards the local Docker socket to the container.
- /var/run/docker.sock:/var/run/docker-host.sock

# Uncomment the next four lines if you will use a ptrace-based debuggers like C++, Go, and Rust.
# cap_add:
# - SYS_PTRACE
# security_opt:
# - seccomp:unconfined

# Overrides default command so things don't shut down after the process ends.
entrypoint: /usr/local/share/docker-init.sh
command: sleep infinity

171 changes: 171 additions & 0 deletions .devcontainer/library-scripts/common-debian.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------

# Syntax: ./common-debian.sh [install zsh flag] [username] [user UID] [user GID] [upgrade packages flag]

INSTALL_ZSH=${1:-"true"}
USERNAME=${2:-"vscode"}
USER_UID=${3:-1000}
USER_GID=${4:-1000}
UPGRADE_PACKAGES=${5:-"true"}

set -e

if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi

# Treat a user name of "none" as root
if [ "${USERNAME}" = "none" ] || [ "${USERNAME}" = "root" ]; then
USERNAME=root
USER_UID=0
USER_GID=0
fi

# Load markers to see which steps have already run
MARKER_FILE="/usr/local/etc/vscode-dev-containers/common"
if [ -f "${MARKER_FILE}" ]; then
echo "Marker file found:"
cat "${MARKER_FILE}"
source "${MARKER_FILE}"
fi

# Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive

# Function to call apt-get if needed
apt-get-update-if-needed()
{
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}

# Run install apt-utils to avoid debconf warning then verify presence of other common developer tools and dependencies
if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then
apt-get-update-if-needed

PACKAGE_LIST="apt-utils \
git \
openssh-client \
less \
iproute2 \
procps \
curl \
wget \
unzip \
nano \
jq \
lsb-release \
ca-certificates \
apt-transport-https \
dialog \
gnupg2 \
libc6 \
libgcc1 \
libgssapi-krb5-2 \
libicu[0-9][0-9] \
liblttng-ust0 \
libstdc++6 \
zlib1g \
locales \
sudo"

# Install libssl1.1 if available
if [[ ! -z $(apt-cache --names-only search ^libssl1.1$) ]]; then
PACKAGE_LIST="${PACKAGE_LIST} libssl1.1"
fi

# Install appropriate version of libssl1.0.x if available
LIBSSL=$(dpkg-query -f '${db:Status-Abbrev}\t${binary:Package}\n' -W 'libssl1\.0\.?' 2>&1 || echo '')
if [ "$(echo "$LIBSSL" | grep -o 'libssl1\.0\.[0-9]:' | uniq | sort | wc -l)" -eq 0 ]; then
if [[ ! -z $(apt-cache --names-only search ^libssl1.0.2$) ]]; then
# Debian 9
PACKAGE_LIST="${PACKAGE_LIST} libssl1.0.2"
elif [[ ! -z $(apt-cache --names-only search ^libssl1.0.0$) ]]; then
# Ubuntu 18.04, 16.04, earlier
PACKAGE_LIST="${PACKAGE_LIST} libssl1.0.0"
fi
fi

echo "Packages to verify are installed: ${PACKAGE_LIST}"
apt-get -y install --no-install-recommends ${PACKAGE_LIST} 2> >( grep -v 'debconf: delaying package configuration, since apt-utils is not installed' >&2 )

PACKAGES_ALREADY_INSTALLED="true"
fi

# Get to latest versions of all packages
if [ "${UPGRADE_PACKAGES}" = "true" ]; then
apt-get-update-if-needed
apt-get -y upgrade --no-install-recommends
apt-get autoremove -y
fi

# Ensure at least the en_US.UTF-8 UTF-8 locale is available.
# Common need for both applications and things like the agnoster ZSH theme.
if [ "${LOCALE_ALREADY_SET}" != "true" ]; then
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
locale-gen
LOCALE_ALREADY_SET="true"
fi

# Create or update a non-root user to match UID/GID - see https://aka.ms/vscode-remote/containers/non-root-user.
if id -u $USERNAME > /dev/null 2>&1; then
# User exists, update if needed
if [ "$USER_GID" != "$(id -G $USERNAME)" ]; then
groupmod --gid $USER_GID $USERNAME
usermod --gid $USER_GID $USERNAME
fi
if [ "$USER_UID" != "$(id -u $USERNAME)" ]; then
usermod --uid $USER_UID $USERNAME
fi
else
# Create user
groupadd --gid $USER_GID $USERNAME
useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME
fi

# Add add sudo support for non-root user
if [ "${EXISTING_NON_ROOT_USER}" != "${USERNAME}" ]; then
echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME
chmod 0440 /etc/sudoers.d/$USERNAME
EXISTING_NON_ROOT_USER="${USERNAME}"
fi

# Ensure ~/.local/bin is in the PATH for root and non-root users for bash. (zsh is later)
if [ "${DOT_LOCAL_ALREADY_ADDED}" != "true" ]; then
echo "export PATH=\$PATH:\$HOME/.local/bin" | tee -a /root/.bashrc >> /home/$USERNAME/.bashrc
chown $USER_UID:$USER_GID /home/$USERNAME/.bashrc
DOT_LOCAL_ALREADY_ADDED="true"
fi

# Optionally install and configure zsh
if [ "${INSTALL_ZSH}" = "true" ] && [ ! -d "/root/.oh-my-zsh" ] && [ "${ZSH_ALREADY_INSTALLED}" != "true" ]; then
apt-get-update-if-needed
apt-get install -y zsh
curl -fsSLo- https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh | bash 2>&1
echo "export PATH=\$PATH:\$HOME/.local/bin" >> /root/.zshrc
if [ "${USERNAME}" != "root" ]; then
cp -fR /root/.oh-my-zsh /home/$USERNAME
cp -f /root/.zshrc /home/$USERNAME
sed -i -e "s/\/root\/.oh-my-zsh/\/home\/$USERNAME\/.oh-my-zsh/g" /home/$USERNAME/.zshrc
chown -R $USER_UID:$USER_GID /home/$USERNAME/.oh-my-zsh /home/$USERNAME/.zshrc
fi
ZSH_ALREADY_INSTALLED="true"
fi

# Write marker file
mkdir -p "$(dirname "${MARKER_FILE}")"
echo -e "\
PACKAGES_ALREADY_INSTALLED=${PACKAGES_ALREADY_INSTALLED}\n\
LOCALE_ALREADY_SET=${LOCALE_ALREADY_SET}\n\
EXISTING_NON_ROOT_USER=${EXISTING_NON_ROOT_USER}\n\
DOT_LOCAL_ALREADY_ADDED=${DOT_LOCAL_ALREADY_ADDED}\n\
ZSH_ALREADY_INSTALLED=${ZSH_ALREADY_INSTALLED}" > "${MARKER_FILE}"
Loading