How does gitlab-ci works internally with gitlab runner? - docker

I have some specific questions regarding gitlab-ci and runner:
If my specific runner is configured in kubernetes cluster then how code mirroring happens into runner from Gitlab code repository
How does the build happens in runner when it is configured within kubernetes cluster?
When using any docker image in my .gitlab-ci.yml, how does those images are pulled by runner and how does commands mentioned within "script" tag are executed into those docker containers? Does runner creates pods within the kubernetes cluster (where runner is configured) with the image mentioned within .gitlab-ci.yml, and executes commands within those containers?
Any additional explanations or references to learning material on how Gitlab runner works internally is highly appreciated.

I'm assuming when you say your GitLab Runner is configured in Kubernetes you mean you're using the Kubernetes executor. I marked the sections relevant to your questions.
(1) GitLab CI pulls the code from the repository (if public it's not an issue, but you can also use a private registry). Basically a helper image is used to clone the repository and download any artifacts into a container.
The Kubernetes executor lets you use an existing Kubernetes cluster to execute your pipeline/build step by calling the Kubernetes cluster API and creating a new Pod, with both build and services containers for each job. (3)
A more detailed view of the steps a Runner takes:
Prepare: Create the Pod against the Kubernetes Cluster. This creates the containers required for the build and services to run.
Pre-build: Clone, restore cache and download artifacts from previous stages. This is run on a special container as part of the Pod. (2)
Build: User build.
Post-build: Create cache, upload artifacts to GitLab. This also uses the special container as part of the Pod.
The GitLab repository for the runners might also be interesting for you.

Related

Test Docker image on Kubernetes, without Docker Daemon

I am new in containers, so I will try to explain my issue as detailed as I can.
I run a Jenkins flow on a Kubernetes agent, that builds a Docker image and push it on a repository. I want to modify the Jenkins flow so the image is tested (some functional tests) before pushed to the repository. I found this project on Github https://github.com/GoogleContainerTools/container-structure-test that is convenient for testing, but unfortunately it requires Docker Daemon that is not available on my Kubernetes agent.
Has anyone tried this before? Or does anyone know any workaround? Thanks!
I tried to include a docker container in the pod I use for the Kubernetes agent, create a separate testing file and use this container to run the tests for the image (without the use of the Github project). However, the absence of Docker Daemon is the problem in this case as well.
For running containers inside Jenkins on Kuberntes agents, you can either use Jenkins Docker in Docker agent or Jenkins Podman agent which is a containerless docker alternative with the same cli.
Then, encapsulate tests in a container image and run them inside either of the above agents.
Disclaimer: I wrote above posts.
Also note that there's an option not to use docker daemon for the project you mentioned. Use tar driver instead.

How to create a docker container inside docker in the GitLab CI/CD pipeline?

Since I do not have lots of experience with DevOps yet, I am struggling with finding an answer for the following question:
I'm setting up the CI/CD pipeline for my project (Python, FastAPI, Redis), which will have test and build stages. It can be described as follows:
Before stages: Install all dependencies (install python, copy files for testing, etc.)
The test stage uses docker-compose for running the Redis server, which is
necessary to launch the application for testing (unit test).
The build stage creates a new docker container
and pushes it to the Docker Hub if there is a new Gitlab tag.
The GitLab Runner is located on the AWS EC2 instance, the runner executor is a "docker" with an "Ubuntu:20.04" image. So, the question:
How to run "docker-compose"/"docker build" inside the docker executor and whether it can be done at all without any negative consequences?
I thought about several options:
Switch from docker executor to something else (maybe to shell or docker+ssh)
Use Docker-in-Docker, but I see cautions that it can be dangerous and not sure exactly why in my case.
What I've tried:
To use Redis as "services" in Gitlab job instead of docker-compose file, but I can't find a way to bind my application (host and port) to a server that runs inside the docker executor as a service.

Spinning Docker / ECS containers from Jenkins Docker container

I had setup Jenkins using the Jenkins Docker Image on an AWS ECS Cluster with just one EC2 instance.
After the initial setup, I tried running the hello-world pipeline from Jenkins documentation. I see that I am getting "docker: not found"
I understand that this is because Docker is not installed and available within the Jenkins Docker container. However, I have a fundamental question on whether I should proceed with installing Docker inside the running Jenkins Docker container (to use that as the base image) or not. When I researched around, I found this blog post and this SO Answer.
I wanted to follow these suggestions and I tried mounting the volume /usr/bin/docker and the socket /var/run/docker.sock from the host EC2 / ECS instance to the Jenkins Container. After this, when I ran the docker version command to test the setup, I am getting linux library issues - docker: error while loading shared libraries: libltdl.so.7: cannot open shared object file: No such file or directory which indicates that the setup did not go well.
Here are my questions -
How to run Jenkins pipelines that use Docker containers when running Jenkins based on a Docker container? I want to be able to pull / build / run docker containers, say for example - run the hello-world pipeline example referenced above?
My end goal is to create 2 types of Jenkins jobs that do the following -
Jenkins Job Type 1
Check out repository from BitBucket cloud
Run a shell script to build a docker image for a java project (possibly using the maven jib plugin)
Publish to AWS ECR. (assuming this can be done using the cloudbees plugin)
Jenkins Job Type 2
Pull the image published from Job Type 1 from AWS ECR
Create a container from the image (which essentially runs the java application)
The container itself could be run on the same Jenkins ECR cluster with slaves. But, again should the slaves have docker installed within them to pull and run the image from ECR?
Asking these questions after a good amount of research and not finding answers. Any guidance is appreciated. Thanks.
I Googled the docker error you included in your post and found this StackOverflow post.
You have to install libltdl-dev in order to get everything working correctly
Since the errors are identical I suggest you give it a shot. As per the post, install libltdl-dev in the docker container.

Docker and Gitlab - how to modify the docker run

I'm very new to contentious integration with Docker and Gitlab.
I have a situation where my script in .gitlab-ci.yml needs to encode files with ioncube, but that's now fully possible due to some security restrictions that Docker has placed. Therefore, I need to modify the docker run command that Gitlab runs when I start a job for my Gitlab project.
According to this page...
In addition, a change to the Docker security options on the container will be required to allow for the licensing process to function by using the –security-opt seccomp:unconfined option to the docker run command.
I need to adding that extra parameter to the docker run call, but since Gitlab does that somewhere, I have no idea how to proceed.
Is there a way I can get Gitlab to include –security-opt seccomp:unconfined when I run a job?
EDIT: I host Gitlab on my own server.
The GitLab CI Process executes it's Pipeline stages/builds via a GitLab Runner. (https://docs.gitlab.com/runner/).
The GitLab Runner is registered to a GitLab instance or a specific GitLab Project. The configuration that you specify in the gitlab-ci.yml file is what gets executed by the Runner. In your case, you're specifying the GitLab Runner to execute a Docker container.
There is some advanced configuration that you can do with the GitLab Runners (https://docs.gitlab.com/runner/configuration/advanced-configuration.html). The setting that you are looking for is in this section: https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-docker-section.
On the server that is hosting your GitLab Runner (or in the Docker instance that is hosting your GitLab Runner) modify the config.toml file (probably at /etc/gitlab-runner/config.toml). You should see a [runners.docker] section if you've registered this Runner to execute Docker containers. It is in this section that you want to add in:
security_opt: ["seccomp:unconfined"]

Easiest way to do docker build command within Jenkinsfile running on Jenkins slave node?

Basic example of what I want my Jenkinsfile to do:
node {
sh 'docker build -t foo/bar .'
}
It seems like I need to install docker onto the Jenkins slave image that's executing my Jenkinsfile. Is there an easy way of doing this? (That Jenkins slave image is itself a docker container)
Are my assumptions correct?
When running with Jenkins master/slaves, the Jenkinsfile is executed by a Jenkins slave
Jenkins plugins installed via the Manage Plugins section (e.g. the Docker Plugin, or Gcloud SDK plugin) are only installed on the Jenkins masters, therefore I would need to manually build my Jenkins slave docker image and install docker on the image?
Since I also need access to the 'gcloud' command (I'm running Jenkins via Kubernetes Helm/Charts), I've been using the gcr.io/cloud-solutions-images/jenkins-k8s-slave image for my Jenkins slave.
Currently it errors out saying "docker: not found"
My assumption is that you want to docker build inside the Jenkins slave (which is a Kubernetes pod, I assume created by the Kubernetes Jenkins Plugin)
To set the stage, when Kubernetes creates pod that will act as a Jenkins slave, all commands that you execute inside the node will be executed inside that Kubernetes pod, inside one of the containers there (by default there will only be one container, but more on this later).
So you are actually trying to run a Docker command inside a container based on gcr.io/cloud-solutions-images/jenkins-k8s-slave, which is most likely based on the official Jenkins JNLP Slave, which does not container Docker!
From this point forward, there are two approaches that you can take:
use a slightly modified image based on the JNLP slave that also contains the Docker client and mount the Docker socket (/var/run/docker.sock) inside the container.
(You can find details on this approach here).
Here is an image that contains the Docker client and kubectl.
Here is a complete view of how to configure the Jenkins Plugin:
Note that you use a different image (you can create your own and add any binary you want there) and that you mount the Docker socket inside the container.
the problem with the first approach is that you create a new image forked from the official JNLP slave and manually add the Docker client. This means that whenever Jenkins or Docker have updates, you need to manually update your image and entire configuration, which is not that desirable.
Using the second approach you always use official images, and you use the JNLP slave to start other containers in the same pod.
Here is the full file from the image below
Here is the Jenkins Plugin documentation for doing this
As I said, the JNLP image will start a container that you specify in the same pod. Note that in order to use Docker from a container you still need to mount the Docker sock.
These are the two ways I found to achieve building images inside a Jenkins JNLP slave running inside a container.
The example also shows how to push the image using credential bindings from Jenkins, and how to update a Kubernetes deployment as part of the build process.
Some more resources:
deploy Jenkins to Kubernetes as Helm chart, configure plugins to install
Thanks,
Radu M

Resources