Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Docker rootless mode & fix file ownership in root mode #771

Merged
merged 5 commits into from
Feb 17, 2022
Merged
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
6 changes: 6 additions & 0 deletions Dockerfile.custom
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
# for a customer using the Cloud Posse Reference Architecture.
# Use it as a basis for your own customizations.
#
# Note that Geodesic supports runtime customizations that
# do not require a custome Dockerfile. See:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# do not require a custome Dockerfile. See:
# do not require a custom Dockerfile. See:

# https://github.com/cloudposse/geodesic/blob/master/docs/customization.md
#
# See Dockerfile.options for some common options you might want.
#
# Note that the version numbers in this file are not maintained,
# you will want to update them to current versions when you start
# and then have a plan for regularly updating them as you go along.
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ deps: init
docker tag $(DOCKER_IMAGE_NAME) $(DOCKER_IMAGE_NAME_BASE)

%.install:
@docker run --rm --env DOCKER_IMAGE --env DOCKER_TAG $(DOCKER_IMAGE_NAME) | bash -s $(DOCKER_TAG) || (echo "Try: sudo make install"; exit 1)
@docker run --rm --env DOCKER_IMAGE --env DOCKER_TAG $(DOCKER_IMAGE_NAME) | bash -s $(DOCKER_TAG)

build: $(DOCKER_BASE_OS).build

Expand Down
9 changes: 8 additions & 1 deletion Makefile.custom
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
# Modify the variable settings to create your own version of Geodesic
# with your own Docker image name and app name.
#
# See Dockerfile.custom and Dockerfile.options for
# how to customize your Dockerfile.
# Note that Geodesic supports runtime customizations that
# do not require a custom Dockerfile: See
# https://github.com/cloudposse/geodesic/blob/master/docs/customization.md
#
#
# The `make` variables build up to $(DOCKER_IMAGE):$(DOCKER_TAG) being
# what you would use for `docker run` and `docker push`.
# You probably want to use either `latest` or `dev` for DOCKER_TAG
Expand Down Expand Up @@ -47,7 +54,7 @@ push:

## Install wrapper script from geodesic container
install:
@docker run --rm $(DOCKER_IMAGE_NAME) | bash -s $(DOCKER_TAG) || (echo "Try: sudo make install"; exit 1)
@docker run --rm $(DOCKER_IMAGE_NAME) | bash -s $(DOCKER_TAG)

## Start the geodesic shell by calling wrapper script
run:
Expand Down
60 changes: 58 additions & 2 deletions docs/customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,54 @@ how to configure the customization.

## DESCRIPTION

Users can place bash shell scripts on their host computer, to be read either at the start of `bash` profile
A great deal of customization can be implemented by placing shell scripts
on the host computer, to be read either at the start of `bash` profile
script processing or at the end of it. These shell scripts can set up environment variables, command
aliases, shell functions, etc. and through setting environment variables, can cause Geodesic to
enable or disable certain features.

Due to technical limitations, there are a small number of options
that can only be controlled via command line options or corresponding (exported)
shell environment variables set in the user's shell before launching
Geodesic via the wrapper script (which is the default and recommended way to launch Geodesic).

Users can also choose whether to have a single `bash` history file
for all containers or to have separate history files.

### Command line options (also environment variables)

Geodesic accepts a small number of command line options, which can also be
set by corresponding (exported) shell environment variables. In all cases,
the command line options must be introduced with double dashes and be
set via `=`. Boolean options can be set `=true` with no argument on the command line.
Command line options are lower case with words separated by dashes,
while environment variables are upper case with words separated by underscored.

Valid:
```bash
geodesic --env-file=~/.geodesic/extra-envs
ENV_FILE=~/.geodesic/extra_envs geodesic
geodesic --geodesic-host-bindfs-enabled
```

Not valid:
```bash
geodesic --env-file ~/.geodesic/extra-envs
env-file=~/.geodesic/extra-envs
ENV-FILE=~/.geodesic/extra-envs
GEODESIC_HOST_BINDFS_ENABLED= geodesic
```

At the moment, underscores are accepted instead of dashes in command line arguments,
but this behavior should not be relied on:

Works, but not officially supported:
```bash
geodesic --env-file=~/.geodesic/extra_envs
```

TODO: Document all the command line options in [geodesic(1)](geodesic.md)

### Root directory for configuration

All configuration files are stored under `$GEODESIC_CONFIG_HOME`, which defaults to `/localhost/.geodesic`.
Expand All @@ -36,26 +76,42 @@ then files would go in `~/work/config/geodesic/` and below on your Docker host m

### Resources

There are currently 3 Resources used for configuration:
There are currently 5 Resources used for configuration:
- Preferences, which are shell scripts loaded very early in the launch of the Geodesic shell.
- Overrides, which are shell scripts loaded very late in the launch of the Geodesic shell.
- `bash` history files, which store `bash` command line history.
- A file of environment variable settings passed to `docker --env-file`
- Command-line options (which can also be set by correspondingly named shell environment variables)

Additionally, when Geodesic exits normally, it will run the host command `geodesic_on_exit`
if it is available. This is intended to be a script that you write and install
anywhere on your PATH to do whatever cleanup you want. For example, change the window title.

#### Preferences and Overrides

Both preferences and overrides can be either a single file, named `preferences` and `overrides` respectively,
or can be a collection of files in directories named `preferences.d` and `overrides.d`.
If they are directories, all the visible files in the directories will be sourced,
except for hidden files and files with names matching the `GEODESIC_AUTO_LOAD_EXCLUSIONS` regex,
which defaults to `(~|.bak|.log|.old|.orig|.disabled)$`.

#### History files

`bash` history is always stored in a single file named `history`, never a directory of files
nor files with any other name. If you want to use a separate history file for one
Geodesic-based Docker image not shared by other Geodesic-based Docker images, you
must create an empty `history` file in the image-specific configuration directory (see below).

#### Environment file

Geodesic passes a single argument to Docker's `--env-file` option when launching
via the installed wrapper script. By default, that file is `~/.geodesic/env`
but that file name can be set via the `--geodesic-default-env-file` command line
option or the `GEODESIC_DEFAULT_ENV_FILE` environment variable.

A second environment file can be specified in addition to the default via the
`--env-file` command line option or `ENV_FILE`

### Configuration by file placement
Resources can be in several places, and will be loaded from most general to most specific, according to the name of the docker container image.

Expand Down
12 changes: 12 additions & 0 deletions os/alpine/Dockerfile.alpine
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ RUN python3 -m pip install --upgrade pip setuptools wheel && \
pip install $(grep cryptography /requirements.txt) && \
pip install -r /requirements.txt --ignore-installed --prefix=/dist --no-build-isolation --no-warn-script-location

### While we have gcc installed, we take advantage of that and build bindfs
### Use fuse (FUSE 2) rather than fuse3 for consistency with Debian
RUN apk add curl fuse fuse-dev
RUN curl -qOsSL https://bindfs.org/downloads/bindfs-1.15.1.tar.gz
RUN tar zxf bindfs-1.15.1.tar.gz && cd bindfs-1.15.1/ && \
./configure && make && make install


#
# Google Cloud SDK
#
Expand Down Expand Up @@ -111,6 +119,9 @@ WORKDIR /tmp
# Copy python dependencies
COPY --from=python /dist/ /usr/

# Install bindfs
COPY --from=python /usr/local/bin/bindfs /usr/local/bin/bindfs

#
# Install Google Cloud SDK
#
Expand Down Expand Up @@ -151,6 +162,7 @@ ADD https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_COMPLETION_VERSI
ARG KUBE_PS1_VERSION
ADD https://raw.githubusercontent.com/jonmosco/kube-ps1/v${KUBE_PS1_VERSION}/kube-ps1.sh /etc/profile.d/prompt:kube-ps1.sh

RUN chmod 755 /etc/bash_completion.d/kubens.sh /etc/bash_completion.d/kubectx.sh /etc/profile.d/prompt:kube-ps1.sh

#
# Install helm
Expand Down
1 change: 1 addition & 0 deletions os/alpine/packages-alpine.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
busybox-extras
diffutils
drill
fuse
fzf-bash-completion
iputils
keybase-client@testing
Expand Down
3 changes: 2 additions & 1 deletion os/debian/Dockerfile.debian
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ COPY packages.txt os/debian/packages-debian.txt /etc/apt/
## Here is where we would copy in the repo checksum in an attempt to ensure updates bust the Docker build cache

# Add CloudPosse package repo
RUN apt-get update && apt-get install -y apt-utils && apt-get install -y curl
RUN apt-get update && apt-get install -y apt-utils curl
RUN curl -1sLf 'https://dl.cloudsmith.io/public/cloudposse/packages/cfg/setup/bash.deb.sh' | bash

# Install Google package repo
Expand Down Expand Up @@ -178,6 +178,7 @@ ADD https://raw.githubusercontent.com/ahmetb/kubectx/v${KUBECTX_COMPLETION_VERSI
ARG KUBE_PS1_VERSION
ADD https://raw.githubusercontent.com/jonmosco/kube-ps1/v${KUBE_PS1_VERSION}/kube-ps1.sh /etc/profile.d/prompt:kube-ps1.sh

RUN chmod 755 /etc/bash_completion.d/kubens.sh /etc/bash_completion.d/kubectx.sh /etc/profile.d/prompt:kube-ps1.sh

#
# Install helm
Expand Down
1 change: 1 addition & 0 deletions os/debian/packages-debian.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Essential debian-only packages
bindfs
default-mysql-client
dnsutils
inetutils-ftp
Expand Down
14 changes: 7 additions & 7 deletions rootfs/etc/motd
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@

IMPORTANT:
* Unless there were errors reported above,
* your host $HOME directory should be mounted to `/localhost`, and
* your host AWS configuration and credentials should be available.
* Use Leapp on your host computer to manage your credentials.
* Leapp is free, open source, and available from https://leapp.cloud
* Use AWS_PROFILE environment variable to manage your AWS IAM role.
* You can interactively select AWS profiles via the `assume-role` command.
# Unless there were errors reported above,
# * Your host $HOME directory should be available under `/localhost`
# * Your host AWS configuration and credentials should be available
# * Use Leapp on your host computer to manage your credentials
# * Leapp is free, open source, and available from https://leapp.cloud
# * Use AWS_PROFILE environment variable to manage your AWS IAM role
# * You can interactively select AWS profiles via the `assume-role` command


Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Files in the profile.d directory are executed by the lexicographical order of their file names.
# This file is named _colors.sh. The leading underscore is needed to ensure this file executes before
# other files that depend on the functions defined here. This file has no dependencies and should come first.
# This file is named _10-colors.sh. The leading underscore is needed to ensure this file executes before
# other files that depend on the functions defined here. The number portion is to ensure proper ordering among
# the high-priority scripts
# This file has no dependencies and should come first.
function red() {
echo "$(tput setaf 1)$*$(tput setaf 0)"
}
Expand Down Expand Up @@ -32,4 +34,4 @@ function bold() {
# The terminal does not support color
printf "%s\n" "$*"
fi
}
}
29 changes: 29 additions & 0 deletions rootfs/etc/profile.d/_20-localhost.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Files in the profile.d directory are executed by the lexicographical order of their file names.
# This file is named _20-localhost.sh. The leading underscore is needed to ensure this file executes before
# other files that depend on the file system mapping defined here.
# The number portion is to ensure proper ordering among the high-priority scripts.
# This file has only depends on colors.sh and should come before any scripts that
# attempt to access files on the host via `/localhost`.

if [[ $SHLVL == 1 ]] && [[ -n $GEODESIC_HOST_UID ]] && [[ -n $GEODESIC_HOST_GID ]] &&
[[ -n $GEODESIC_LOCALHOST ]] && df -a | grep -q " ${GEODESIC_LOCALHOST}\$"; then
if [[ $(df -a | grep ' /localhost$' | cut -f1 -d' ') == ${GEODESIC_LOCALHOST} ]]; then
echo "# Host file ownership mapping already configured"
export GEODESIC_LOCALHOST_MAPPED_DEVICE="${GEODESIC_LOCALHOST}"
elif df -a | grep -q ' /localhost$'; then
red "# Host filesystems found mounted at both /localhost and /localhost.bindfs."
red "# * Verify that content under /localhost is what you expect."
red "# * Report the issue at https://github.com/cloudposse/geodesic/issues"
red "# * Include the output of \`env | grep GEODESIC\` and \`df -a\` in your issue description."
elif bindfs -o nonempty ${GEODESIC_BINDFS_OPTIONS} --create-for-user="$GEODESIC_HOST_UID" --create-for-group="$GEODESIC_HOST_GID" "${GEODESIC_LOCALHOST}" /localhost; then
green "# BindFS mapping of ${GEODESIC_LOCALHOST} to /localhost enabled."
green "# Files created under /localhost will have UID:GID ${GEODESIC_HOST_UID}:${GEODESIC_HOST_GID} on host."
export GEODESIC_LOCALHOST_MAPPED_DEVICE="${GEODESIC_LOCALHOST}"
else
red "# ERROR: Unable to mirror /localhost.bindfs to /localhost"
red "# * Report the issue at https://github.com/cloudposse/geodesic/issues"
red "# * Work around the issue by unsetting shell environment variable GEODESIC_HOST_BINDFS_ENABLED."
red "# * Exiting."
exec false
fi
fi
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Files in the profile.d directory are executed by the lexicographical order of their file names.
# This file is named _geodesic-config.sh. The leading underscore is needed to ensure this file executes before
# other files that depend on the functions defined here.
# This file has depends on _colors.sh and should come second.
# This file is named _30-geodesic-config.sh. The leading underscore is needed to ensure this file
# executes before other files that depend on the functions defined here.
# The number portion is to ensure proper ordering among the high-priority scripts.
# This file defines functions but does not execute them, so it can come anywhere
# before the first script to use one of its functions, such as preferences.sh.

# bash functions that support the user customization framework
#
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Files in the profile.d directory are executed by the lexicographical order of their file names.
# This file is named _preferences.sh. The leading underscore is needed to ensure this file executes before
# other files that depend on the functions defined here.
# This file has depends on _geodesic-config.sh and should come third.
# This file is named _40-preferences.sh. The leading underscore is needed to ensure this file
# executes before other files that depend on the functions defined here.
# The number portion is to ensure proper ordering among the high-priority scripts.
# This file has depends on colors.sh, geodesic-config.sh, and localhost.sh and should come after them.
# This file loads user preferences/customizations and must load before any user-visible configuration takes place.

# In case this output is being piped into a shell, print a warning message
Expand Down Expand Up @@ -58,13 +59,13 @@ elif [[ ! -d $GEODESIC_CONFIG_HOME ]]; then
fi

if [[ ! -d $GEODESIC_CONFIG_HOME ]]; then
if ! df | grep -q /localhost; then
if [[ -z $KUBERNETES_PORT ]]; then
if ! df -a | grep -q " ${GEODESIC_LOCALHOST:-/localhost}\$"; then
if [[ -n $KUBERNETES_PORT ]]; then
echo $(green Kubernetes host detected, Geodesic customization disabled.)
else
red "########################################################################################" >&2
red "# No filesystem is mounted at $(bold /localhost) which limits Geodesic functionality." >&2
red "# No filesystem is mounted at $(bold ${GEODESIC_LOCALHOST:-/localhost}) which limits Geodesic functionality." >&2
boot install
else
echo $(green Kubernetes host detected, Geodesic customization disabled.)
fi
export GEODESIC_CUSTOMIZATION_DISABLED="/localhost not a volume"
elif mkdir -p $GEODESIC_CONFIG_HOME; then
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Files in the profile.d directory are executed by the lexicographical order of their file names.
# This file sets the working directory inside Geodesic to match the host directory Geodesic
# was launched from, if possible. If the host directory is not accessible, it sets the working directory to `/`.
#
# This file is named _workdir.sh. The leading underscore is needed to ensure this file executes before
# other files that may depend on it. The "w" is needed to ensure it is loaded *after* _preferences.sh
# This file is named _50-workdir.sh. The leading underscore is needed to ensure this file
# executes before other files that may depend on it.
# The number portion is to ensure proper ordering among the high-priority scripts.
# This file depends on colors.sh, localhost.sh, and preferences,sh and must come after them
#

# Outputs the device the file resides on, or /dev/null if the file does not exist
function _file_device() {
df --output=source "$1" | tail -1
{ [[ -e $1 ]] && df --output=source "$1" | tail -1; } || echo '/dev/null'
}

# file_on_host is true when the argument is a file or directory that appears to be on the Host file system.
Expand All @@ -16,8 +16,8 @@ function _file_device() {
# Therefore we cache some info in the environment.
if [[ $GEODESIC_LOCALHOST_DEVICE == "disabled" ]]; then
red "# Host filesystem device detection disabled."
elif df -a | grep -q /localhost; then
export GEODESIC_LOCALHOST_DEVICE=$(_file_device /localhost)
elif df -a | grep -q " ${GEODESIC_LOCALHOST:-/localhost}\$"; then
export GEODESIC_LOCALHOST_DEVICE=$(_file_device "${GEODESIC_LOCALHOST:-/localhost}")
if [[ $GEODESIC_LOCALHOST_DEVICE == $(_file_device /) ]]; then
red "# Host filesystem device detection failed. Falling back to \"path starts with /localhost\"."
GEODESIC_LOCALHOST_DEVICE="same-as-root"
Expand All @@ -27,12 +27,13 @@ else
fi

function file_on_host() {
if [[ $GEODESIC_LOCALHOST_DEVICE =~ ^(disabled|missing)$ ]]; then
if [[ $GEODESIC_LOCALHOST_DEVICE =~ ^(disabled|missing)$ ]]; then
return 1
elif [[ $GEODESIC_LOCALHOST_DEVICE == "same-as-root" ]]; then
[[ $(readlink -e "$1") =~ ^/localhost(/.*)?$ ]]
[[ $(readlink -e "$1") =~ ^/localhost ]]
else
[[ $(_file_device "$1") == ${GEODESIC_LOCALHOST_DEVICE} ]]
local dev="$(_file_device "$1")"
[[ $dev == $GEODESIC_LOCALHOST_DEVICE ]] || [[ $dev == $GEODESIC_LOCALHOST_MAPPED_DEVICE ]]
fi
}

Expand All @@ -52,7 +53,7 @@ if [[ -d $GEODESIC_WORKDIR ]]; then
[[ $SHLVL == 1 ]] && green "# Initial working directory configured as ${GEODESIC_WORKDIR}"
else
if [[ -d $GEODESIC_HOST_CWD ]]; then
if [[ -n $LOCAL_HOME ]] && { [[ $GEODESIC_LOCALHOST_DEVICE == "disabled" ]] || $(file_on_host "$GEODESIC_HOST_CWD"); }; then
if [[ -n $LOCAL_HOME ]] && { [[ $GEODESIC_LOCALHOST_DEVICE == "disabled" ]] || file_on_host "$GEODESIC_HOST_CWD"; }; then
export GEODESIC_WORKDIR=$(readlink -e "${GEODESIC_HOST_CWD}")
green "# Initial working directory set from host CWD to ${GEODESIC_WORKDIR}"
else
Expand Down
2 changes: 1 addition & 1 deletion rootfs/etc/profile.d/atmos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ function atmos_configure_base_path() {
# Leave $ATMOS_BASE_PATH alone if it is already set
if [[ -n $ATMOS_BASE_PATH ]]; then
if [[ $SHLVL == 1 ]]; then
green "# Using configured $ATMOS_BASE_PATH of \"$ATMOS_BASE_PATH\""
green "# Using configured ATMOS_BASE_PATH of \"$ATMOS_BASE_PATH\""
fi
return
fi
Expand Down
Loading