Skip to main content

Prepare the Toolbox Image

Geodesic is a powerful Linux toolbox container designed to optimize DevOps workflows by providing essential dependencies for a DevOps toolchain, ensuring consistency and efficiency across development environments without additional software installation on your workstation. It can be extended and customized to fit specific needs by creating your own Dockerfile based on Geodesic, allowing you to add your favorite tools and share the container with your team for a unified working environment.

NOTE:

Geodesic is similar in principle to devcontainers. However, being a container itself, Geodesic can run anywhere containers are supported—whether on your local workstation, remotely inside clusters, or on bastion hosts. Additionally, you can use Geodesic as the base image for a devcontainer.

Geodesic in action.

Building the Toolbox Image

Build a Geodesic infrastructure container. This container that has all the tools like terraform and atmos for building infrastructure. It's built from the Dockerfile and there are some predefined targets defined in the Makefile to make this easy. Customize these for your organization. Here are examples of both for reference.

Dockerfile
# https://github.com/cloudposse/geodesic/
ARG GEODESIC_VERSION=2.5.0
ARG GEODESIC_OS=debian
# https://github.com/cloudposse/atmos
ARG ATMOS_VERSION=1.63.0
# This should match the version set in stacks/catalog/spacelift.yaml
# This should match the version set in .github/workflows/auto-format.yaml
ARG TF_1_VERSION=1.4.5

FROM public.ecr.aws/cloudposse/geodesic:${GEODESIC_VERSION}-${GEODESIC_OS}

# Geodesic message of the Day
ENV MOTD_URL="https://geodesic.sh/motd"

# Some configuration options for Geodesic
ENV AWS_SAML2AWS_ENABLED=false
ENV AWS_VAULT_ENABLED=false
ENV AWS_VAULT_SERVER_ENABLED=false
ENV CHAMBER_KMS_KEY_ALIAS=aws/ssm
ENV GEODESIC_TF_PROMPT_ACTIVE=false
ENV DIRENV_ENABLED=false

# Enable advanced AWS assume role chaining for tools using AWS SDK
# https://docs.aws.amazon.com/sdk-for-go/api/aws/session/
ENV AWS_SDK_LOAD_CONFIG=1
ENV AWS_DEFAULT_REGION=us-east-1
ENV AWS_DEFAULT_SHORT_REGION=use1
ENV AWS_REGION_ABBREVIATION_TYPE=short
# Install specific versions of Terraform. Must match versions in Spacelift terraform_version_map
# in components/terraform/spacelift/default.auto.tfvars
ARG TF_1_VERSION
RUN apt-get update && apt-get install -y -u --allow-downgrades \
terraform-1="${TF_1_VERSION}-*" && \
update-alternatives --set terraform /usr/share/terraform/1/bin/terraform

ARG ATMOS_VERSION
RUN apt-get update && apt-get install -y --allow-downgrades \
atmos="${ATMOS_VERSION}-*" \
spacectl

# Install pluto - a CLI tool to help discover deprecated and removed apiVersions in Kubernetes
# https://pluto.docs.fairwinds.com/
# https://github.com/FairwindsOps/pluto
RUN apt-get update && apt-get install -y --allow-downgrades \
pluto

COPY rootfs/ /


ARG DOCKER_REPO
ARG TENANT="core"
ENV NAMESPACE=acme
# Format of Geodesic banner prompt
ENV BANNER=${NAMESPACE}
ENV DOCKER_IMAGE="${NAMESPACE}/infra"
ENV DOCKER_TAG="latest"

# Default AWS_PROFILE
ENV AWS_PROFILE=${NAMESPACE}-identity
# This sets the default AWS_CONFIG to be used after signing in with Leapp.
# Once logged in, this config file gives you access to all the other teams
# and roles (if you are authorized for access).
ENV AWS_CONFIG_FILE=/etc/aws-config/aws-config-teams
ENV ASSUME_ROLE_INTERACTIVE_QUERY=${NAMESPACE}${TENANT:+-$TENANT}-gbl-

WORKDIR /
Makefile
export DOCKER_ORG ?= acme
export DOCKER_TAG ?= latest
export ECR_IMAGE ?= infra-acme
export DOCKER_IMAGE ?= $(DOCKER_ORG)/$(ECR_IMAGE)
export DOCKER_IMAGE_NAME ?= $(DOCKER_IMAGE):$(DOCKER_TAG)

# Name for app (used in banner and name of wrapper script)
export APP_NAME ?= acme

# Default install path, if lacking permissions, ~/.local/bin will be used instead
export INSTALL_PATH ?= /usr/local/bin

export TARGET_DOCKER_AWS_ACCOUNT_ID ?= 111111111111

export TARGET_DOCKER_AWS_REGION ?= us-east-1
export TARGET_DOCKER_REGISTRY := $(TARGET_DOCKER_AWS_ACCOUNT_ID).dkr.ecr.$(TARGET_DOCKER_AWS_REGION).amazonaws.com
export TARGET_DOCKER_REPO := $(TARGET_DOCKER_REGISTRY)/$(DOCKER_IMAGE)
export TARGET_VERSION ?= $(DOCKER_TAG)
export TARGET_IMAGE_NAME := $(TARGET_DOCKER_REPO):$(TARGET_VERSION)
export TARGET_DOCKER_PUSH_PROFILE ?= acme-core-gbl-artifacts-admin

export ADR_DOCS_DIR = docs/adr
export ADR_DOCS_README = $(ADR_DOCS_DIR)/README.md

-include $(shell curl -sSL -o .build-harness "https://cloudposse.tools/build-harness"; echo .build-harness)

.DEFAULT_GOAL := all

.PHONY: all build build-clean install run run/new run/check push


all: init deps build install run/new
@exit 0

## Install dependencies (if any)
deps: init
@exit 0

## Build docker image
build: export DOCKER_FILE=components/docker/infra-acme/Dockerfile
build:
@$(MAKE) --no-print-directory docker/build

## Build docker image with no cache
build-clean: export DOCKER_BUILD_FLAGS=--no-cache
build-clean: build
@exit 0

## Push docker image to registry
push:
@docker tag $(DOCKER_IMAGE_NAME) $(TARGET_IMAGE_NAME)
@docker push $(TARGET_IMAGE_NAME)

## Install wrapper script from geodesic container
install:
@docker run --rm \
--env APP_NAME=$(APP_NAME) \
--env DOCKER_IMAGE=$(DOCKER_IMAGE) \
--env DOCKER_TAG=$(DOCKER_TAG) \
--env INSTALL_PATH=$(INSTALL_PATH) \
$(DOCKER_IMAGE_NAME) | bash -s $(DOCKER_TAG)

## Start the geodesic shell by calling wrapper script
run:
@$(APP_NAME)

run/check:
@if [[ -n "$$(docker ps --format {{ '{{ .Names }}' }} --filter name="^/$(APP_NAME)\$$")" ]]; then \
printf "**************************************************************************\n" ; \
printf "Not launching new container because old container is still running.\n"; \
printf "Exit all running container shells gracefully or kill the container with\n\n"; \
printf " docker kill %s\n\n" "$(APP_NAME)" ; \
printf "**************************************************************************\n" ; \
exit 9 ; \
fi

run/new: run/check run
@exit 0

.PHONY: terraform-rm-lockfiles rebuild-adr-docs rebuild-aws-config rebuild-docs ecr-auth

## Remove all lock files
terraform-rm-lockfiles:
$(shell find . -name ".terraform.lock.hcl" -exec rm -v {} \;)

## Rebuild README for all Terraform components
rebuild-docs: packages/install/terraform-docs
@pre-commit run --all-files terraform_docs

## Rebuild README TOC for all ADRs
rebuild-adr-docs:
adr generate toc > $(ADR_DOCS_README);

rebuild-aws-config:
@printf "\nTo rebuild the AWS configuration files, from within the Geodesic shell ($(APP_NAME)), run:\n\n" >&2
@printf " atmos workflow update-aws-config -f identity\n\n" >&2
exit 1

## Authenticate with ECR repository
ecr-auth:
@AWS_PROFILE=$(TARGET_DOCKER_PUSH_PROFILE) aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $(TARGET_DOCKER_REPO)

The standard Makefile includes a number of commands. In order to build the initial, complete Geodesic image, run the following:

make all

On future builds, use make run to use the cached image.

Alias

We install a wrapper script with make all to your chosen namespace. For example, simply enter for given namespace to start your Geodesic container once built:

acme

See the install step of the Makefile for more details.

Build the toolbox image locally before continuing.

Follow the toolbox image setup steps in the How-to Get Started guide. In short, run make all.

The container will have the given local home mapped, so you should be able to use aws normally inside it once you set a profile that has valid credentials. For instance, if I log in to the profile acme with leapp, I can run aws --profile acme sts get-caller-identity and get a response.

Once you've verified that the infra container has access to aws resources, we can move on to the next step.

What comes next?

With your repository set up, workstation configured and toolbox in hand, you're ready to get to work provisioning your infrastructure with Atmos and Terraform. The next step is to learn how to provision AWS accounts.

Next Step