Skip to content
Draft
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
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,14 @@ The following is a minimal setup command to install chezmoi and my dotfiles from
## ⚙️ Install & Setup Application Individually

This repository provides for the installation and setup of each application individually.
The desired application can be installed as follows (e.g., docker installation on MacOS):
The desired application can be installed as follows (e.g., Apple Container and Socktainer installation on MacOS):

```shell
bash install/macos/common/docker.sh
bash install/macos/common/container.sh
```

On macOS, `DOCKER_HOST` defaults to `unix://${HOME}/.socktainer/container.sock` so Docker-compatible clients can talk to Socktainer.

Each installation script can be found under the [`./install`](https://github.com/shunk031/dotfiles/tree/main/install) directory.

## 🛠️ Update & Test 🧪
Expand All @@ -96,10 +98,10 @@ To verify that the updated scripts work correctly, run the scripts on the actual
The setup scripts are stored as shellscripts in an appropriate location under the [`./install`](https://github.com/shunk031/dotfiles/tree/main/install) directory.
After verifying that the shellscript works, store the [chezmoi template](https://www.chezmoi.io/user-guide/templating/)-based file, which is based on the shellscript, in an appropriate location under the [`./home/.chezmoiscripts`](https://github.com/shunk031/dotfiles/tree/main/home/.chezmoiscripts) directory.

Below is the correspondence between shellscript and template for docker installation on MacOS.
Below is the correspondence between shellscript and template for Apple Container and Socktainer installation on MacOS.

- The shellscript for docker: [`install/macos/common/docker.sh`](https://github.com/shunk031/dotfiles/blob/main/install/macos/common/docker.sh)
- The chezmoi template for docker: [`home/.chezmoiscripts/macos/run_once_10-install-docker.sh.tmpl`](https://github.com/shunk031/dotfiles/blob/main/home/.chezmoiscripts/macos/run_once_10-install-docker.sh.tmpl)
- The shellscript for Apple Container and Socktainer: [`install/macos/common/container.sh`](https://github.com/shunk031/dotfiles/blob/main/install/macos/common/container.sh)
- The chezmoi template for Apple Container and Socktainer: [`home/.chezmoiscripts/macos/run_once_12-install-container.sh.tmpl`](https://github.com/shunk031/dotfiles/blob/main/home/.chezmoiscripts/macos/run_once_12-install-container.sh.tmpl)

### 💾 Test on the Local Machine

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{{ if eq .chezmoi.os "darwin" -}}
{{ include "../install/macos/common/container.sh" }}
{{ end -}}
10 changes: 10 additions & 0 deletions home/dot_config/exact_sheldon/plugin_sources/client/macos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,13 @@ function _macos_browser() {
}
zsh-defer _macos_browser
'''

[plugins.socktainer-docker-host]
inline = '''
function _socktainer_docker_host() {
if [[ -z "$DOCKER_HOST" && "$OSTYPE" == darwin* ]]; then
export DOCKER_HOST="unix://${HOME}/.socktainer/container.sock"
fi
}
zsh-defer _socktainer_docker_host
'''
114 changes: 114 additions & 0 deletions install/macos/common/container.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/usr/bin/env bash

# @file install/macos/common/container.sh
# @brief Install Apple Container and Socktainer on macOS.
# @description
# Installs or removes the Apple Container and Socktainer Homebrew formulae
# and starts their services on supported non-CI macOS hosts.

set -Eeuo pipefail

if [ "${DOTFILES_DEBUG:-}" ]; then
set -x
fi

#
# @description Return the host macOS major version.
#
function macos_major_version() {
sw_vers -productVersion | cut -d "." -f 1
}

#
# @description Check whether Apple Container and Socktainer can run on this host.
#
function is_container_stack_supported_macos() {
local major_version
major_version="$(macos_major_version)"

[ "$(uname -m)" = "arm64" ] && [ "${major_version}" -ge 26 ]
}

#
# @description Remove the legacy Apple Container cask when it is installed.
#
function uninstall_legacy_container_cask() {
if brew list --cask container &> /dev/null; then
brew uninstall --cask container --force
fi
}

#
# @description Check whether a Homebrew formula is installed.
# @arg $1 string Homebrew formula token.
#
function is_formula_installed() {
local formula_token="$1"

brew list --formula "${formula_token}" &> /dev/null
}

#
# @description Install Apple Container and Socktainer Homebrew formulae.
#
function install_container() {
if "${CI:-false}"; then
echo "Skipping Apple Container and Socktainer install in CI."
return
fi

if ! is_container_stack_supported_macos; then
echo "Skipping Apple Container and Socktainer install because Apple Silicon macOS 26 or newer is required."
return
fi

uninstall_legacy_container_cask
brew tap socktainer/tap
brew install container socktainer/tap/socktainer
}

#
# @description Start the Apple Container and Socktainer services on supported non-CI hosts.
#
function start_container_system() {
if "${CI:-false}" || ! is_container_stack_supported_macos; then
return
fi

brew services start container
brew services start socktainer
}

#
# @description Remove Apple Container and Socktainer Homebrew packages.
#
function uninstall_container() {
if "${CI:-false}" || ! is_container_stack_supported_macos; then
return
fi

local formula_token

brew services stop socktainer || true
brew services stop container || true

for formula_token in socktainer container; do
if is_formula_installed "${formula_token}"; then
brew uninstall "${formula_token}" --force
fi
done

uninstall_legacy_container_cask
}

#
# @description Run the Apple Container and Socktainer installation flow.
#
function main() {
install_container
start_container_system
}

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main
fi
87 changes: 77 additions & 10 deletions install/macos/common/docker.sh
Original file line number Diff line number Diff line change
@@ -1,35 +1,102 @@
#!/usr/bin/env bash

# @file install/macos/common/docker.sh
# @brief Install Docker Desktop on macOS.
# @brief Remove Docker Desktop from macOS.
# @description
# Installs or removes the Docker Desktop cask through Homebrew.
# Stops Docker Desktop, removes the Homebrew cask when present, and clears
# stale Docker Desktop helper links.

set -Eeuo pipefail

if [ "${DOTFILES_DEBUG:-}" ]; then
set -x
fi

readonly DOCKER_DESKTOP_CASK_TOKENS=(
docker-desktop
docker
)
readonly DOCKER_DESKTOP_HELPER_LINKS=(
/usr/local/bin/docker
/usr/local/bin/docker-credential-desktop
/usr/local/bin/docker-credential-ecr-login
/usr/local/bin/docker-credential-osxkeychain
/usr/local/bin/hub-tool
/usr/local/bin/kubectl.docker
/usr/local/cli-plugins/docker-compose
)

#
# @description Check whether a Homebrew cask is installed.
# @arg $1 string Homebrew cask token.
#
function is_cask_installed() {
local cask_token="$1"

brew list --cask "${cask_token}" &> /dev/null
}

#
# @description Stop Docker Desktop if the application helper is available.
#
function stop_docker_desktop() {
if [ -x "/Applications/Docker.app/Contents/MacOS/com.docker.backend" ]; then
"/Applications/Docker.app/Contents/MacOS/com.docker.backend" -quit || true
fi

osascript -e 'quit app "Docker"' &> /dev/null || true
}

#
# @description Remove Docker Desktop Homebrew casks installed under known tokens.
#
function uninstall_docker_desktop() {
local cask_token

for cask_token in "${DOCKER_DESKTOP_CASK_TOKENS[@]}"; do
if is_cask_installed "${cask_token}"; then
brew uninstall --cask "${cask_token}" --force
fi
done
}

#
# @description Remove stale Docker Desktop helper symlinks.
#
function remove_docker_desktop_helper_links() {
local helper_link

for helper_link in "${DOCKER_DESKTOP_HELPER_LINKS[@]}"; do
if [ -L "${helper_link}" ]; then
rm -f "${helper_link}"
fi
done
}

#
# @description Install the Docker Desktop Homebrew cask.
# @description Remove the Docker Desktop application bundle when it remains.
#
function install_docker() {
brew install --cask docker
function remove_docker_desktop_app_bundle() {
if [ -d "/Applications/Docker.app" ]; then
rm -rf "/Applications/Docker.app"
fi
}

#
# @description Remove the Docker Desktop Homebrew cask.
# @description Remove Docker Desktop from this macOS host.
#
function uninstall_docker() {
brew uninstall --cask docker --force
function remove_docker_desktop() {
stop_docker_desktop
uninstall_docker_desktop
remove_docker_desktop_helper_links
remove_docker_desktop_app_bundle
}

#
# @description Run the Docker Desktop installation flow.
# @description Run the Docker Desktop removal flow.
#
function main() {
install_docker
remove_docker_desktop
}

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
Expand Down
22 changes: 22 additions & 0 deletions tests/install/macos/common/container.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bats

readonly SCRIPT_PATH="./install/macos/common/container.sh"

function setup() {
source "${SCRIPT_PATH}"
}

function teardown() {
run uninstall_container
}

@test "[macos] container and socktainer" {
run env DOTFILES_DEBUG=1 bash "${SCRIPT_PATH}"

[ "${status}" -eq 0 ]

if ! "${CI:-false}" && is_container_stack_supported_macos; then
[ -x "$(command -v container)" ]
[ -x "$(command -v socktainer)" ]
fi
}
9 changes: 2 additions & 7 deletions tests/install/macos/common/docker.bats
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,8 @@ function setup() {
source "${SCRIPT_PATH}"
}

function teardown() {
run uninstall_docker
}

@test "[macos] docker" {
@test "[macos] remove docker desktop" {
DOTFILES_DEBUG=1 bash "${SCRIPT_PATH}"

[ -x "$(command -v docker)" ]
# [ -x "$(command -v docker-compose)" ]
[ ! -d "/Applications/Docker.app" ]
}
Loading