Installing GitLab CE into Containers.
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↗,
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.
- I exit the container:
exit
NOTE: I exit the
root
account to use theyt
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 thesshd_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
- I reboot the container:
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.
Updating the Container for Docker.
- From the terminal, I create a
btrfs
storage pool calleddocker
:
lxc storage create docker btrfs
- In the
docker
pool, I create a new storage volume calledGitLabVol
:
lxc storage volume create docker GitLabVol
- I attach the
GitLab
container to theGitLabVol
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
- I
restart
the container:
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-p
arents flag:
sudo mkdir -p /srv/gitlab
- I define the
GITLAB_HOME
environment variable:
export GITLAB_HOME=/srv/gitlab
- I reboot the container:
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.
- I run Docker Compose:
docker compose up -d
NOTE 1: Docker Compose is
-d
etached 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.
- I exit the container:
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.
I add the IP address to a browser.
I login to the
root
account.
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
Subscribe to my newsletter
Read articles from Brian King directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Brian King
Brian King
Thank you for reading this post. My name is Brian and I'm a developer from New Zealand. I've been interested in computers since the early 1990s. My first language was QBASIC. (Things have changed since the days of MS-DOS.) I am the managing director of a one-man startup called Digital Core (NZ) Limited. I have accepted the "12 Startups in 12 Months" challenge so that DigitalCore will have income-generating products by April 2024. This blog will follow the "12 Startups" project during its design, development, and deployment, cover the Agile principles and the DevOps philosophy that is used by the "12 Startups" project, and delve into the world of AI, machine learning, deep learning, prompt engineering, and large language models. I hope you enjoyed this post and, if you did, I encourage you to explore some others I've written. And remember: The best technologies bring people together.