Published on: March 3, 2025
5 min read
Use this easy-to-follow tutorial to create a secure, ephemeral, reproducible development environment in GitLab that can replace your local environments.
Development environments often require the ability to build and run containers as part of their local development. Securely running containers within containers can be challenging. This article will provide a step-by-step guide to securely build and run containers in a workspace.
You will learn how to:
Install the AWS
CLI
on your local machine. Next, configure a named
profile and
export it to ensure all the following aws
commands use the set
credentials.
aws configure --profile gitlab-workspaces-container-demo
export AWS_PROFILE=gitlab-workspaces-container-demo
Install eksctl, a CLI to interact with
AWS EKS. Let’s now create a Kubernetes 1.31 cluster on AWS EKS with 1 node
of Ubuntu 22.04 of c5.2xlarge
instance type. The nodes can autoscale from
0-20 nodes and each node will have a label sysbox-install: yes
. This will
be explained later in the article.
export CLUSTER_NAME="gitlab-workspaces-container-demo-eks-sysbox"
eksctl create cluster \
--name "${CLUSTER_NAME}" \
--version 1.31 \
--node-ami-family=Ubuntu2204 \
--nodes=1 \
--nodes-min=0 \
--nodes-max=20 \
--instance-types=c5.2xlarge \
--node-labels "sysbox-install=yes" \
--asg-access \
--external-dns-access \
--full-ecr-access
Create an IAM OIDC provider for your cluster.
eksctl utils associate-iam-oidc-provider --cluster "${CLUSTER_NAME}"
--approve
Create IAM role for EBS add-on for EKS.
eksctl create iamserviceaccount \
--name ebs-csi-controller-sa \
--namespace kube-system \
--cluster "${CLUSTER_NAME}" \
--role-name "AmazonEKS_EBS_CSI_DriverRole_${CLUSTER_NAME}" \
--role-only \
--attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
--approve
Create Amazon EBS CSI driver add-on for Amazon EKS cluster.
eksctl utils describe-addon-versions --kubernetes-version 1.31 | grep
aws-ebs-csi-driver
export AWS_ACCOUNT_ID="UPDATE_ME"
eksctl create addon \
--cluster "${CLUSTER_NAME}" \
--name aws-ebs-csi-driver \
--version latest \
--service-account-role-arn "arn:aws:iam::${AWS_ACCOUNT_ID}:role/AmazonEKS_EBS_CSI_DriverRole_${CLUSTER_NAME}" \
--force
Install kubectl, a command line tool for communicating with a Kubernetes cluster's control plane, using the Kubernetes API.
Let’s get the kubeconfig of the created cluster.
aws eks update-kubeconfig --name "${CLUSTER_NAME}"
Sysbox is a container runtime that improves container isolation and enables containers to run the same workloads as virtual machines.
Install Sysbox on the
Kubernetes cluster using the sysbox-deploy-k8s daemonset
.
curl
https://raw.githubusercontent.com/nestybox/sysbox/refs/tags/v0.6.6/sysbox-k8s-manifests/sysbox-install.yaml
-o sysbox-install.yaml
Because of how Sysbox releases itself, it first created a git tag, which
runs a pipeline to build assets after which the YAML files for the
sysbox-deploy-k8s daemonset
are updated. Thus, we need to update the
DaemonSet's spec.template.soec.containers[0].image
to
registry.nestybox.com/nestybox/sysbox-deploy-k8s:v0.6.6-0
.
new_image_value="registry.nestybox.com/nestybox/sysbox-deploy-k8s:v0.6.6-0"
temp_file=$(mktemp)
sed -E "s|^([[:space:]]*image:)[[:space:]]*.*|\1 $new_image_value|"
"sysbox-install.yaml" > "$temp_file"
mv "$temp_file" "sysbox-install.yaml"
Apply the YAML file to Kubernetes and ensure all the pods of the DaemonSet are running.
kubectl apply -f sysbox-install.yaml
kubectl get pod -A
kubectl -n kube-system get daemonset
Verify the installation by creating a pod which uses Sysbox container runtime.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: sysbox-verification-pod
namespace: default
annotations:
io.kubernetes.cri-o.userns-mode: "auto:size=65536"
spec:
runtimeClassName: sysbox-runc
containers:
- image: "hello-world"
imagePullPolicy: Always
name: main
restartPolicy: Always
EOF
kubectl -n default get pod sysbox-verification-pod
kubectl exec -it sysbox-verification-pod -- echo "Pod is running
successfully on a Kubernetes cluster configured with Sysbox."
kubectl -n default delete pod sysbox-verification-pod
Follow our documentation tutorial to set up GitLab agent and GitLab Workspaces Proxy.
Follow our documentation to configure sudo access for a workspace with Sysbox.
Setup Ingress NGINX Controller for Kubernetes
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
--force-update
helm repo update
helm upgrade --install \
ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace \
--version 4.11.1 \
--timeout=600s --wait --wait-for-jobs
kubectl -n ingress-nginx get pod
We’ll use example-go-http-app as the project to create a workspace from. Open the workspace, start a terminal, and install Docker.
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o
/etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") 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-buildx-plugin docker-compose-plugin
# Start the Docker Daemon
sudo dockerd
Build the container image.
sudo docker build -t workspaces-golang-server .
Let’s run the container built above and expose port 3000 from the container onto the host (workspace).
sudo docker run -p 3000:3000 workspaces-golang-server
The port 3000
is exposed in the
.devfile.yaml
used to create the workspace. Access the server running inside the container
from the browser. Here is a video clip.
From GitLab 17.4, you can build and run containers securely in GitLab Workspaces. See our documentation for more information. Replace your local development environments to GitLab Workspaces for a secure, ephemeral, reproducible development environment.