2023-01-23 19:37:35 -08:00
{{- if ne .host.distro.family "windows" -}}
#!/usr/bin/env bash
2023-04-11 20:57:02 -07:00
# @file Docker Install
# @brief Ensures Docker is installed, ensures the user can access Docker without sudo, and ensures Docker is configured to use gVisor
# @description
# This script ensures Docker is installed and then adds the provisioning user to the `docker` group so that they can
# access Docker without `sudo`. It also installs and configures gVisor for use with Docker.
#
# ## gVisor
#
# gVisor is included with our Docker setup because it improves the security of Docker. gVisor is an application kernel, written in Go,
# that implements a substantial portion of the Linux system call interface. It provides an additional layer of isolation between running
# applications and the host operating system. It has gained a lot of attention, perhaps partly, because it is maintained by Google.
2023-01-23 19:37:35 -08:00
2023-01-24 20:36:59 -08:00
{{ includeTemplate "universal/profile-before" }}
{{ includeTemplate "universal/logg-before" }}
2023-01-23 19:37:35 -08:00
### Install Docker
if [ -d /Applications ] && [ -d /System ]; then
# macOS
2023-01-24 21:10:11 -08:00
if [ ! -d /Applications/Docker.app ]; then
logg info 'Installing Docker on macOS via Homebrew cask'
brew install --cask docker
else
logg info 'Docker appears to be installed already'
fi
2023-01-23 19:37:35 -08:00
logg info 'Opening the Docker for Desktop app so that the Docker engine starts running'
2023-01-23 20:29:20 -08:00
open --background -a Docker
2023-01-23 19:37:35 -08:00
elif command -v apt-get > /dev/null; then
. /etc/os-release
if [ " $ ID " == 'ubuntu' ]; then
logg info 'Installing Docker on Ubuntu'
else
logg info 'Installing Docker on Debian'
fi
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings
2023-01-23 21:06:39 -08:00
curl -fsSL "https://download.docker.com/linux/ $ ID /gpg" | sudo gpg --dearmor --yes -o /etc/apt/keyrings/docker.gpg
2023-01-23 19:37:35 -08:00
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ $ ID $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
elif command -v dnf > /dev/null; then
2023-01-25 05:18:43 -08:00
. /etc/os-release
if [ " $ ID " == 'centos' ]; then
logg info 'Installing Docker on CentOS'
elif [ " $ ID " == 'fedora' ]; then
logg info 'Installing Docker on Fedora'
else
logg error 'Unknown OS - cannot install Docker' && exit 1
fi
2023-01-23 19:37:35 -08:00
sudo dnf -y install dnf-plugins-core
2023-01-25 05:18:43 -08:00
sudo dnf config-manager --add-repo "https://download.docker.com/linux/ $ ID /docker-ce.repo"
2023-01-23 19:37:35 -08:00
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
elif command -v yum > /dev/null; then
# CentOS
logg info 'Installing Docker on CentOS'
sudo yum install -y yum-utils
2023-01-24 15:46:10 -08:00
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
2023-01-23 19:37:35 -08:00
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
elif command -v apk > /dev/null; then
# Alpine
logg info 'Installing Docker on Alpine'
sudo apk add --update docker
elif command -v pacman > /dev/null; then
# Archlinux
logg info 'Installing Docker on Archlinux'
sudo pacman -Syu
sudo pacman -S docker
elif command -v zypper > /dev/null; then
# OpenSUSE
logg info 'Installing Docker on OpenSUSE'
sudo zypper addrepo https://download.docker.com/linux/sles/docker-ce.repo
sudo zypper install docker-ce docker-ce-cli containerd.io docker-compose-plugin
fi
### Add Docker group on Linux
if command -v groupadd > /dev/null; then
# Linux
2023-01-23 20:59:44 -08:00
if ! cat /etc/group | grep docker > /dev/null; then
logg info 'Creating Docker group'
sudo groupadd docker
fi
2023-01-23 19:37:35 -08:00
logg info 'Adding user to Docker group'
sudo usermod -aG docker " $ USER "
fi
### Boot Docker on start with systemd on Linux machines
if command -v systemctl > /dev/null; then
# Systemd Linux
sudo systemctl start docker.service
sudo systemctl enable docker.service
sudo systemctl enable containerd.service
fi
2023-02-03 21:21:52 -08:00
### Installs pre-built gVisor using method recommended on official website
function gVisorPreBuilt() {
logg info 'Installing gVisor using method recommended on official website'
set -e
mkdir /tmp/gvisor && cd /tmp/gvisor
ARCH=$(uname -m)
URL="https://storage.googleapis.com/gvisor/releases/release/latest/ ${ ARCH } "
logg info 'Downloading gVisor `runsc` and `containerd-shim-runsc-v1` SHA signatures'
wget " ${ URL } /runsc ${ URL } /runsc.sha512" " ${ URL } /containerd-shim-runsc-v1 ${ URL } /containerd-shim-runsc-v1.sha512"
sha512sum -c runsc.sha512 -c containerd-shim-runsc-v1.sha512
rm -f *.sha512
chmod a+rx runsc containerd-shim-runsc-v1
sudo mv runsc containerd-shim-runsc-v1 /usr/local/bin
}
### Installs gVisor using alternate Go method described on the GitHub page
function gVisorGo() {
# Official build timed out - use Go method
logg info 'Installing gVisor using the Go fallback method'
sudo chown -Rf "$(whoami)" /usr/local/src/gvisor
cd /usr/local/src/gvisor
echo "module runsc" > go.mod
GO111MODULE=on go get gvisor.dev/gvisor/runsc@go
CGO_ENABLED=0 GO111MODULE=on sudo -E go build -o /usr/local/bin/runsc gvisor.dev/gvisor/runsc
GO111MODULE=on sudo -E go build -o /usr/local/bin/containerd-shim-runsc-v1 gvisor.dev/gvisor/shim
}
### Installs gVisor using the [GitHub developer page method](https://github.com/google/gvisor#installing-from-source). This method requires Docker to be installed
function gVisorSource() {
### Ensure sources are cloned / up-to-date
logg info 'Building gVisor from source'
if [ -d /usr/local/src/gvisor ]; then
cd /usr/local/src/gvisor
sudo git reset --hard HEAD
sudo git clean -fxd
sudo git pull origin master
else
sudo git clone https://github.com/google/gvisor.git /usr/local/src/gvisor
fi
2023-02-15 19:14:33 -08:00
2023-02-03 21:21:52 -08:00
### Build gVisor
cd /usr/local/src/gvisor
sudo mkdir -p bin
# Wait 5 minutes for build to finish, and if it does not use Go
# TODO - Generate container-shim-runsc-v1 as well (low priority since this method is not used and is only recommended for development)
sudo timeout 300 make copy TARGETS=runsc DESTINATION=bin/
if [ -f ./bin/runsc ]; then
sudo cp ./bin/runsc /usr/local/bin
else
logg error 'Timed out while building `runsc` from source' && exit 6
fi
}
2023-01-23 20:29:20 -08:00
### Add gVisor
if [ ! -d /Applications ] || [ ! -d /System ]; then
# Linux
if ! command -v runsc > /dev/null; then
# Install gVisor
2023-02-03 21:21:52 -08:00
gVisorPreBuilt || PRE_BUILT_EXIT_CODE=$?
if [ -n " $ PRE_BUILT_EXIT_CODE " ]; then
logg warn 'gVisor failed to install using the pre-built method'
gVisorGo || GO_METHOD_EXIT_CODE=$?
if [ -n " $ GO_METHOD_EXIT_CODE " ]; then
logg warn 'gVisor failed to install using the Go fallback method'
gVisorSource || SOURCE_EXIT_CODE=$?
if [ -n " $ SOURCE_EXIT_CODE " ]; then
logg error 'All gVisor installation methods failed' && exit 1
else
logg success 'gVisor installed via source'
fi
else
logg success 'gVisor installed via Go fallback method'
fi
2023-02-03 20:53:29 -08:00
else
2023-02-03 21:21:52 -08:00
logg success 'gVisor installed from pre-built Google-provided binaries'
2023-02-03 20:53:29 -08:00
fi
2023-02-03 21:03:36 -08:00
else
logg info '`runsc` is installed'
2023-01-23 20:29:20 -08:00
fi
2023-02-03 21:03:36 -08:00
### Ensure Docker is configured to use runsc
2023-01-23 20:29:20 -08:00
if [ ! -f /etc/docker/daemon.json ]; then
# Configure Docker to use gVisor
# Create /etc/docker/daemon.json
logg info 'Creating /etc/docker'
sudo mkdir -p /etc/docker
2023-01-24 22:09:28 -08:00
if [ -f /usr/local/src/install.doctor/home/dot_config/docker/daemon.json ]; then
2023-01-23 21:47:23 -08:00
logg info 'Creating /etc/docker/daemon.json'
2023-01-24 22:09:28 -08:00
sudo cp "/usr/local/src/install.doctor/home/dot_config/docker/daemon.json" /etc/docker/daemon.json
2023-01-23 21:47:23 -08:00
else
2023-01-24 22:09:28 -08:00
logg warn '/usr/local/src/install.doctor/home/dot_config/docker/daemon.json is not available so the /etc/docker/daemon.json file cannot be populated'
2023-01-23 21:47:23 -08:00
fi
2023-02-03 21:03:36 -08:00
# Restart / enable Docker
2023-02-15 19:14:33 -08:00
if [[ ! "$(test -d /proc && grep Microsoft /proc/version > /dev/null)" ]] && command -v systemctl > /dev/null; then
2023-02-03 21:03:36 -08:00
logg info 'Restarting Docker service'
sudo systemctl restart docker.service
sudo systemctl restart containerd.service
fi
# Test Docker /w runsc
2023-02-03 21:21:52 -08:00
logg info 'Testing that Docker can load application with `runsc`'
2023-02-03 21:03:36 -08:00
docker run --rm --runtime=runsc hello-world || RUNSC_EXIT_CODE=$?
if [ -n " $ RUNSC_EXIT_CODE " ]; then
logg error 'Failed to run the Docker hello-world container with runsc' && exit 5
2023-02-03 21:21:52 -08:00
else
logg success 'Docker successfully ran the hello-world container with `runsc`'
2023-02-03 21:03:36 -08:00
fi
2023-01-23 20:29:20 -08:00
fi
fi
2023-01-23 19:37:35 -08:00
{{ end -}}