Git Product home page Git Product logo

envbuilder's Introduction

envbuilder

discord release godoc license

Build development environments from a Dockerfile on Docker, Kubernetes, and OpenShift. Allow developers to modify their environment in a tight feedback loop.

  • Supports devcontainer.json and Dockerfile
  • Cache image layers with registries for speedy builds
  • Runs on Kubernetes, Docker, and OpenShift

Quickstart

The easiest way to get started is to run the envbuilder Docker container that clones a repository, builds the image from a Dockerfile, and runs the $INIT_SCRIPT in the freshly built container.

/tmp/envbuilder is used to persist data between commands for the purpose of this demo. You can change it to any directory you want.

docker run -it --rm \
    -v /tmp/envbuilder:/workspaces \
    -e GIT_URL=https://github.com/coder/envbuilder-starter-devcontainer \
    -e INIT_SCRIPT=bash \
    ghcr.io/coder/envbuilder

Edit .devcontainer/Dockerfile to add htop:

$ vim .devcontainer/Dockerfile
- RUN apt-get install vim sudo -y
+ RUN apt-get install vim sudo htop -y

Exit the container, and re-run the docker run command... after the build completes, htop should exist in the container! ๐Ÿฅณ

Container Registry Authentication

envbuilder uses Kaniko to build containers. You should follow their instructions to create an authentication configuration.

After you have a configuration that resembles the following:

{
  "auths": {
    "https://index.docker.io/v1/": {
      "auth": "base64-encoded-username-and-password"
    }
  }
}

base64 encode the JSON and provide it to envbuilder as the DOCKER_CONFIG_BASE64 environment variable.

Alternatively, if running envbuilder in Kubernetes, you can create an ImagePullSecret and pass it into the pod as a volume mount. This example will work for all registries.

# Artifactory example
kubectl create secret docker-registry regcred \
  --docker-server=my-artifactory.jfrog.io \
  --docker-username=read-only \
  --docker-password=secret-pass \
  [email protected] \
  -n coder
resource "kubernetes_deployment" "example" {
  metadata {
    namespace = coder
  }
  spec {
    spec {
      container {  
        # Define the volumeMount with the pull credentials
        volume_mount {
          name       = "docker-config-volume"
          mount_path = "/envbuilder/config.json"
          sub_path   = ".dockerconfigjson"
        }
      }
      # Define the volume which maps to the pull credentials
      volume {
        name = "docker-config-volume"
        secret {
          secret_name = "regcred"
        }
      }
    }
  }
}

Docker Hub

Authenticate with docker login to generate ~/.docker/config.json. Encode this file using the base64 command:

$ base64 -w0 ~/.docker/config.json
ewoJImF1dGhzIjogewoJCSJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOiB7CgkJCSJhdXRoIjogImJhc2U2NCBlbmNvZGVkIHRva2VuIgoJCX0KCX0KfQo=

Provide the encoded JSON config to envbuilder:

DOCKER_CONFIG_BASE64=ewoJImF1dGhzIjogewoJCSJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOiB7CgkJCSJhdXRoIjogImJhc2U2NCBlbmNvZGVkIHRva2VuIgoJCX0KCX0KfQo=

Git Authentication

GIT_USERNAME and GIT_PASSWORD are environment variables to provide Git authentication for private repositories.

For access token-based authentication, follow the following schema (if empty, there's no need to provide the field):

Provider GIT_USERNAME GIT_PASSWORD
GitHub [access-token]
GitLab oauth2 [access-token]
BitBucket x-token-auth [access-token]
Azure DevOps [access-token]

If using envbuilder inside of Coder, you can use the coder_external_auth Terraform resource to automatically provide this token on workspace creation:

data "coder_external_auth" "github" {
    id = "github"
}

resource "docker_container" "dev" {
    env = [
        GIT_USERNAME = data.coder_external_auth.github.access_token,
    ]
}

Layer Caching

Cache layers in a container registry to speed up builds. To enable caching, authenticate with your registry and set the CACHE_REPO environment variable.

CACHE_REPO=ghcr.io/coder/repo-cache

To experiment without setting up a registry, use LAYER_CACHE_DIR:

docker run -it --rm \
  -v /tmp/envbuilder-cache:/cache \
  -e LAYER_CACHE_DIR=/cache
  ...

Each layer is stored in the registry as a separate image. The image tag is the hash of the layer's contents. The image digest is the hash of the image tag. The image digest is used to pull the layer from the registry.

The performance improvement of builds depends on the complexity of your Dockerfile. For coder/coder, uncached builds take 36m while cached builds take 40s (~98% improvement).

Image Caching

When the base container is large, it can take a long time to pull the image from the registry. You can pre-pull the image into a read-only volume and mount it into the container to speed up builds.

# Pull your base image from the registry to a local directory.
docker run --rm \
  -v /tmp/kaniko-cache:/cache \
  gcr.io/kaniko-project/warmer:latest \
    --cache-dir=/cache \
    --image=<your-image>

# Run envbuilder with the local image cache.
docker run -it --rm \
  -v /tmp/kaniko-cache:/image-cache:ro \
  -e BASE_IMAGE_CACHE_DIR=/image-cache

In Kubernetes, you can pre-populate a persistent volume with the same warmer image, then mount it into many workspaces with the ReadOnlyMany access mode.

Setup Script

The SETUP_SCRIPT environment variable dynamically configures the user and init command (PID 1) after the container build process.

Note TARGET_USER is passed to the setup script to specify who will execute INIT_COMMAND (e.g., code).

Write the following to $ENVBUILDER_ENV to shape the container's init process:

  • TARGET_USER: Identifies the INIT_COMMAND executor (e.g.root).
  • INIT_COMMAND: Defines the command executed by TARGET_USER (e.g. /bin/bash).
  • INIT_ARGS: Arguments provided to INIT_COMMAND (e.g. -c 'sleep infinity').
# init.sh - change the init if systemd exists
if command -v systemd >/dev/null; then
  echo "Hey ๐Ÿ‘‹ $TARGET_USER"
  echo INIT_COMMAND=systemd >> $ENVBUILDER_ENV
else
  echo INIT_COMMAND=bash >> $ENVBUILDER_ENV
fi

# run envbuilder with the setup script
docker run -it --rm \
  -v ./:/some-dir \
  -e SETUP_SCRIPT=/some-dir/init.sh \
  ...

Custom Certificates

  • SSL_CERT_FILE: Specifies the path to an SSL certificate.
  • SSL_CERT_DIR: Identifies which directory to check for SSL certificate files.
  • SSL_CERT_BASE64: Specifies a base64-encoded SSL certificate that will be added to the global certificate pool on start.

envbuilder's People

Contributors

aaronlehmann avatar coryb avatar dependabot[bot] avatar ericpaulsen avatar janlo avatar kconley-sq avatar kylecarbs avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.