TL;DR.
This post provides a step-by-step guide to installing GitLab CE using Docker within an LXC (LinuX Container). I start by explaining the basics of LXD, LXC, and Docker, then move on to the installation processes for each utility. This guide also explores how I set up LXC and Docker, how I download GitLab CE from Docker Hub, and how I resolve common issues. The end result is GitLab CE running in a Docker container within an LXC, offering a more effective, and streamlined, development workflow.
Attributions:
https://ubuntu.com/tutorials/how-to-run-docker-inside-lxd-containers↗,
https://docs.gitlab.com/ee/install/docker.html↗,
https://docs.docker.com/compose/↗.
An Introduction.
Containers are important to a modular development and deployment workflows.
The purpose of this post is to show two container technologies working together.
The Big Picture.
The LXD and LXCs (LinuX Containers) use one type of container technology. Docker uses another type of container technology. Although LXCs and Docker both use containers, they each solve different problems and address their own, specific use cases. LXCs run processes that do not affect other containers, or the host system, and are easily run. Docker encloses, and runs, apps in containers that are easily shared.
This post uses the GitLab CE installation as a way to demonstrate LXC and Docker technologies working together. (Yes, I know this post is a little over the top 😁.)
Prerequisites.
- A Debian-based Linux distro (I use Ubuntu).
Updating my Base System.
- In a terminal, I update my base system:
sudo apt clean && \
sudo apt update && \
sudo apt dist-upgrade -y && \
sudo apt --fix-broken install && \
sudo apt autoclean && \
sudo apt autoremove -y
What is LXD and LXC?
The LXD (LinuX Daemon) is the container manager that is used to create, and manage, LXCs (LinuX Containers). It is a background service that can automatically start LXCs when the host system boots, or stop any container from starting at all.
An LXC (LinuX Container) is an isolated, OS-level virtualization which, for efficiency, uses the Linux kernel of the host system. An LXC is a virtual environment where system processes within the LXC container can not affect other containers, or the host system, without specifically running certain commands.
https://ubuntu.com/server/docs/containers-lxd↗,
https://ubuntu.com/server/docs/containers-lxc↗, and
https://solodev.app/installing-lxd-and-using-lxcs.
Setting Up an LXC.
- I list the existing containers:
lxc ls
NOTE: I need to install LXD if this command fails.
- I launch a new container called GitLab:
lxc launch ubuntu:22.04 GitLab
- I bash into the container:
lxc exec GitLab -- bash
- I update and upgrade the container:
sudo apt clean && \
sudo apt update && \
sudo apt dist-upgrade -y && \
sudo apt --fix-broken install && \
sudo apt autoclean && \
sudo apt autoremove -y
Adding a User Account to the LXC.
- From within the container, I add a new user:
adduser yt
- I add the new user to the
sudo group:
usermod -aG sudo yt
NOTE: usermod let's me (-a)ppend the sudo (-G)roup to the yt account.
exit
NOTE: I exit the root account to use the yt account.
Setting the LXC Home Directory.
- From the terminal, I log in to the container with the
yt account:
lxc exec GitLab -- su yt
NOTE: At the moment, the home directory is /root. This section will address the issue by changing the home directory to ~.
- I use the Nano text editor to open the
.bashrc file:
sudo nano ~/.bashrc
- I copy the following, add it (CTRL + SHIFT + V) to the bottom of the
.bashrc file, save (CTRL +S) the changes, and exit (CTRL + X) Nano:
cd ~
Hardening the Container.
- From within the container, I use the
Nano text editor to open the sshd_config file:
sudo nano /etc/ssh/sshd_config
- I copy the following, add it (CTRL + SHIFT + V) to the bottom of the
sshd_config file, save (CTRL +S) the changes, and exit (CTRL + X) Nano:
PasswordAuthentication no
PermitRootLogin no
Protocol 2
Port 22
NOTE: Port 22 is the default, so I'll choose my own, random, available port number.
- I restart the "ssh" service:
sudo systemctl restart ssh.service
sudo reboot
NOTE: Within the container, I can also install (or enable) UFW, Fail2Ban, and CrowdSec.
What is Docker?
Docker is a tool for easily deploying, and running my applications on any platform. I can package an application with all its code, libraries, dependencies, and tools, which allows me to deploy that app as a single bundle. Docker guarantees that my application will run on any computer that also runs Docker.
https://www.docker.com/↗.
Updating the Container for Docker.
- From the terminal, I create a
btrfs storage pool called docker:
lxc storage create docker btrfs
- In the
docker pool, I create a new storage volume called GitLabVol:
lxc storage volume create docker GitLabVol
- I attach the
GitLab container to the GitLabVol volume:
lxc config device add GitLab docker disk pool=docker source=GitLabVol path=/var/lib/docker
- I change the nested containers setting to true:
lxc config set GitLab security.nesting=true
- I change the intercept system calls setting to true:
lxc config set GitLab security.syscalls.intercept.mknod=true
- I change the emulate system calls setting to true:
lxc config set GitLab security.syscalls.intercept.setxattr=true
lxc restart GitLab
Installing Docker.
- From the terminal, I log in to the container with the
yt account:
lxc exec GitLab -- su yt
NOTE: The home directory (~) for my account was set in the .bashrc file earlier in this post.
- I install the following requirements:
sudo apt install -y ca-certificates curl gnupg lsb-release
- I make a
keyrings directory:
mkdir -m 0755 -p /etc/apt/keyrings
- I add Docker’s official GPG key:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
- I change the mode of the
docker.gpg file:
sudo chmod a+r /etc/apt/keyrings/docker.gpg
- I install the
Docker repository:
echo "deb [arch="$(dpkg --print-architecture)" \
signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
- I update the
homelab repo list:
sudo apt update
- I install
Docker and its requirements:
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Checking the Docker Installation.
- I check if
Docker is active:
systemctl is-active docker
- I check the status of
Docker:
service docker status
- I check the
Docker version:
sudo docker version
- I list the information for Docker:
sudo docker info
- I create the Docker group, if required:
sudo groupadd docker
Setting the Docker Privileges.
- I create the docker group, if required:
sudo groupadd docker
- I add my account to the docker group:
sudo usermod -aG docker $USER
- I log in to the new
docker group (or reboot the container):
newgrp docker
- I verify the Docker installation by running this command without a
sudo prefix:
docker run hello-world
NOTE: This command displays 'Hello from Docker!' if Docker is properly installed.
What is GitLab CE?
GitLab CE (Community Edition) is an open source, end-to-end software development platform with built-in version control, issue tracking, code review, CI/CD, and more.
I can self-host GitLab CE on my own servers, in a container, or on a cloud provider.
Setting the GITLAB_HOME Env.
- I make the
GitLab directory using the -parents flag:
sudo mkdir -p /srv/gitlab
- I define the
GITLAB_HOME environment variable:
export GITLAB_HOME=/srv/gitlab
sudo reboot
Downloading GitLab with Docker Compose.
- From the terminal, I log in to the container with the
yt account:
lxc exec GitLab -- su yt
- I use Nano to create a Docker Compose file called
docker-compose.yml:
sudo nano ./docker-compose.yml
- I copy the following, add it (CTRL + SHIFT + V) to the file, save (CTRL + S) the changes, and exit (CTRL + X) Nano:
version: '3.6'
services:
gitlab:
image: gitlab/gitlab-ce:16.7.5-ce.0
container_name: gitlab
restart: always
hostname: 'gitlab.example.com'
environment:
GITLAB_OMNIBUS_CONFIG: |
# Add any other gitlab.rb configuration here, each on its own line
external_url 'https://gitlab.example.com'
ports:
# These ports are in format <host-port>:<container-port>
- '80:80'
- '443:443'
- '22:22'
volumes:
- '$GITLAB_HOME/config:/etc/gitlab'
- '$GITLAB_HOME/logs:/var/log/gitlab'
- '$GITLAB_HOME/data:/var/opt/gitlab'
shm_size: '256m'
NOTE: Compose V2 ignores the version: '3.6' entry on the first line, which is included for Compose V1 compatibility. Since 2023, V1 is no longer updated.
docker compose up -d
NOTE 1: Docker Compose is -detached from the terminal and runs as a daemon. (A daemon is a service that runs in the background.)
NOTE 2: It will take up to ~5 minutes to start the GitLab service.
- I can stop the Docker container (if required) with the down command:
docker compose down
- I check the logs in real time:
docker compose logs -f -t
- I stop the logs with
CTRL + C.
Setting Up the Root Password.
- I setup the root password:
docker exec -it gitlab gitlab-rake "gitlab:password:reset[root]"
NOTE: Be patient. It can take up to a minute for this command to respond.
exit
Testing GitLab CE.
- From the terminal, I find the IP address for the host interface called
eth0:
lxc ls
NOTE: eth0 was set when the LXD was initialised earlier in this post.
NOTE: It is NEVER a good idea to use the root account of ANY program for running day-to-day operations. This includes local distros and self-hosted services. I ALWAYS create a user account for handling my daily activities.
The Results.
In this post, I walked through the process of installing GitLab CE using Docker in an LXC. I began by discussing the basics of LXD, LXC, and Docker, then moved on to the installation processes for each. I also explored how to set up an LXC and Docker, and how to download GitLab CE from Docker Hub. By following the steps outlined in this guide, I was able to run GitLab CE in a Docker container within an LXC, thereby leveraging the benefits of both containerization technologies for my coding workflow.
In Conclusion.
LXD (LinuX Daemon) is a container manager, while LXCs (LinuX Containers) are isolated, OS-level virtualizations. Docker is a tool that helps with bundling applications into container packages that can run anywhere. GitLab CE is an open-source, end-to-end software development platform and repository. I can self-host everything, or I can push it all to a cloud provider.
So, how did I bring them all together? First, I installed LXD, and then I created an LXC. Next, I updated the LXC to handle Docker and finally, I pulled the latest GitLab CE image from Docker Hub. Voila! I now have GitLab CE running in a Docker container within an LXC.
By leveraging these technologies, my development workflows have become more efficient. And remember: I always keep my systems updated and upgraded for optimal security and performance.
Do you have any thoughts on combining these technologies for your development workflows? Have you tried it before, or are you considering it now? Let's discuss in the comments below!
Until next time: Be safe, be kind, be awesome.
#GitLabCE #Docker #LXC #LXD #DockerInLXC #LinuxContainers #Containerization #DevOps #SoftwareDevelopment #TechGuide #DevelopmentWorkflow