Skip to content

Commit 1d38b14

Browse files
authored
Merge pull request #4 from Lemoncode/feature/jenkins
2 parents 058936d + 71cdc1c commit 1d38b14

39 files changed

+8866
-1
lines changed

.gitignore

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1-
.DS_Store
1+
.DS_Store
2+
3+
# code Jenkins demos
4+
node_modules/
5+
6+
.env
7+
app/
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
FROM jenkinsci/blueocean:latest
2+
3+
USER root
4+
5+
# insatll node
6+
RUN apk add --update nodejs npm
7+
8+
# compose deps
9+
RUN apk add --no-cache \
10+
gcc \
11+
libc-dev \
12+
libffi-dev \
13+
make \
14+
openssl-dev \
15+
python3-dev \
16+
py-pip
17+
18+
# install docker-compose via python
19+
RUN pip install docker-compose
20+
21+
# .NET Core deps
22+
RUN apk add --no-cache \
23+
ca-certificates \
24+
icu-libs \
25+
krb5-libs \
26+
libgcc \
27+
libintl \
28+
libssl1.1 \
29+
libstdc++ \
30+
zlib
31+
32+
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT="true" \
33+
PATH="${PATH}:/root/.dotnet"
34+
35+
# .NET Core SDK
36+
# see https://github.com/dotnet/dotnet-docker/blob/master/3.1/sdk/alpine3.11/amd64/Dockerfile
37+
RUN dotnet_sdk_version=3.1.201 \
38+
&& wget -O dotnet.tar.gz https://dotnetcli.azureedge.net/dotnet/Sdk/$dotnet_sdk_version/dotnet-sdk-$dotnet_sdk_version-linux-musl-x64.tar.gz \
39+
&& dotnet_sha512='9a8f14be881cacb29452300f39ee66f24e253e2df947f388ad2157114cd3f44eeeb88fae4e3dd1f9687ce47f27d43f2805f9f54694b8523dc9f998b59ae79996' \
40+
&& echo "$dotnet_sha512 dotnet.tar.gz" | sha512sum -c - \
41+
&& mkdir -p /usr/share/dotnet \
42+
&& tar -C /usr/share/dotnet -oxzf dotnet.tar.gz \
43+
&& ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet \
44+
&& rm dotnet.tar.gz \
45+
# Trigger first run experience by running arbitrary cmd
46+
&& dotnet help
47+
48+
USER jenkins
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
## Downloading and running Jenkins in Docker
2+
3+
### 1. Create a network for Jenkins
4+
5+
```bash
6+
$ docker network create jenkins
7+
```
8+
9+
### 2. Create the following volumes to share the Docker client TLS certificates needed to connect to the Docker daemon and persist the Jenkins data
10+
11+
```bash
12+
$ docker volume create jenkins-docker-certs
13+
$ docker volume create jenkins-data
14+
```
15+
16+
### 3. In order to execute Docker commands inside Jenkins nodes, download and run the docker:dind Docker image
17+
18+
```bash
19+
docker container run \
20+
--name jenkins-docker \
21+
--rm \
22+
--detach \
23+
--privileged \
24+
--network jenkins \
25+
--network-alias docker \
26+
--env DOCKER_TLS_CERTDIR=/certs \
27+
--volume jenkins-docker-certs:/certs/client \
28+
--volume jenkins-data:/var/jenkins_home \
29+
--publish 2376:2376 \
30+
docker:dind
31+
```
32+
33+
#### Commands explanation
34+
35+
```
36+
docker container run \
37+
--name jenkins-docker \ # 1
38+
--rm \ # 2
39+
--detach \ # 3
40+
--privileged \ # 4
41+
--network jenkins \ # 5
42+
--network-alias docker \ # 6
43+
--env DOCKER_TLS_CERTDIR=/certs \ # 7
44+
--volume jenkins-docker-certs:/certs/client \ # 8
45+
--volume jenkins-data:/var/jenkins_home \ # 9
46+
--publish 2376:2376 \ # 10
47+
docker:dind # 11
48+
```
49+
50+
1. The Docker container name.
51+
2. Removes the Docker container instance when it is shut down.
52+
3. Runs the Docker container in the background.
53+
4. Running Docker in Docker currently requires privileged access to function properly.
54+
5. Join to previous created network.
55+
6. Makes the Docker in Docker container available as the hostname _docker_ within the _jenkins_ network.
56+
7. Enables the use of TLS in the Docker server. Due to the use of a privileged container, this is recommended, though it requires the use of the shared volume described below. This environment variable controls the root directory where Docker TLS certificates are managed.
57+
8. Maps the _/certs/client_ directory inside the container to a Docker volume named _jenkins-docker-certs_ as created above.
58+
9. Maps the _/var/jenkins_home_ directory inside the container to the Docker volume named _jenkins-data_ as created above. This will allow for other Docker containers controlled by this Docker container's Docker daemon to mount data from Jenkins.
59+
10. Exposes the Docker daemon port on the host machine. This is useful for executing _docker_ commands on the host machine to control this inner Docker daemon.
60+
11. The _docker:dind_ image itself.
61+
62+
### 4. Run jenkins as a container
63+
64+
```bash
65+
docker container run \
66+
--name jenkins-blueocean \
67+
--rm \
68+
--detach \
69+
--network jenkins \
70+
--env DOCKER_HOST=tcp://docker:2376 \
71+
--env DOCKER_CERT_PATH=/certs/client \
72+
--env DOCKER_TLS_VERIFY=1 \
73+
--publish 8080:8080 \
74+
--publish 50000:50000 \
75+
--volume jenkins-data:/var/jenkins_home \
76+
--volume jenkins-docker-certs:/certs/client:ro \
77+
jenkinsci/blueocean
78+
```
79+
80+
#### Commands explanation
81+
82+
```
83+
docker container run \
84+
--name jenkins-blueocean \ # 1
85+
--rm \ # 2
86+
--detach \ # 3
87+
--network jenkins \ # 4
88+
--env DOCKER_HOST=tcp://docker:2376 \ # 5
89+
--env DOCKER_CERT_PATH=/certs/client \
90+
--env DOCKER_TLS_VERIFY=1 \
91+
--publish 8080:8080 \ # 6
92+
--publish 50000:50000 \ # 7
93+
--volume jenkins-data:/var/jenkins_home \ # 8
94+
--volume jenkins-docker-certs:/certs/client:ro \ # 9
95+
jenkinsci/blueocean # 10
96+
```
97+
98+
1. Specifies the Docker container name for this instance of the _jenkinsci/blueocean_ Docker image.
99+
100+
2. Removes the Docker container instance when it is shut down.
101+
102+
3. Runs the Docker container in the background.
103+
104+
4. Connects this container to the jenkins network defined in the earlier step. This makes the Docker daemon from the previous step available to this Jenkins container through the hostname docker.
105+
106+
5. Specifies the environment variables used by `docker`, `docker-compose`, and other Docker tools to connect to the Docker daemon from the previous step.
107+
108+
6. Maps (i.e. "publishes") port 8080 of the _jenkinsci/blueocean_ container to port 8080 on the host machine. The first number represents the port on the host while the last represents the container's port. Therefore, if you specified _-p 49000:8080_ for this option, you would be accessing Jenkins on your host machine through port 49000.
109+
110+
7. Maps port 50000 of the jenkinsci/blueocean container to port 50000 on the host machine. This is only necessary if you have set up one or more inbound Jenkins agents on other machines, which in turn interact with the _jenkinsci/blueocean_ container (the Jenkins "controller"). Inbound Jenkins agents communicate with the Jenkins controller through TCP port 50000 by default. You can change this port number on your Jenkins controller through the Configure Global Security page. If you were to change the TCP port for inbound Jenkins agents of your Jenkins controller to 51000 (for example), then you would need to re-run Jenkins (via this docker run …​ command) and specify this "publish" option with something like _--publish 52000:51000_, where the last value matches this changed value on the Jenkins controller and the first value is the port number on the machine hosting the Jenkins controller. Inbound Jenkins agents communicate with the Jenkins controller on that port (52000 in this example). Note that WebSocket agents in Jenkins 2.217 do not need this configuration.
111+
112+
8. Maps the _/var/jenkins_home_ directory in the container to the Docker volume with the name _jenkins-data_. Instead of mapping the _/var/jenkins_home_ directory to a Docker volume, you could also map this directory to one on your machine's local file system. For example, specifying the option
113+
_--volume $HOME/jenkins:/var/jenkins_home_ would map the container's _/var/jenkins_home_ directory to the jenkins subdirectory within the _$HOME_ directory on your local machine, which would typically be _/Users/<your-username>/jenkins_ or _/home/<your-username>/jenkins_. Note that if you change the source volume or directory for this, the volume from the _docker:dind_ container above needs to be updated to match this.
114+
115+
9. Maps the _/certs/client_ directory to the previously created _jenkins-docker-certs_ volume. This makes the client TLS certificates needed to connect to the Docker daemon available in the path specified by the _DOCKER_CERT_PATH_ environment variable.
116+
117+
10. The _jenkinsci/blueocean_ Docker image itself.
118+
119+
## Starting Jenkins
120+
121+
To unlock Jenkins we have to paste a password, we can find the password inside the running container, run the following command `cat /var/jenkins_home/secrets/initialAdminPassword` to obtain the initial password
122+
123+
```bash
124+
$ docker container exec jenkins-blueocean cat /var/jenkins_home/secrets/initialAdminPassword
125+
```
126+
127+
Now install the suggested plugins and wait until Jenkins finishes
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/bin/bash
2+
IMAGE=$1
3+
NETWORK=$2
4+
CERTS_VOLUME=$3
5+
DATA_VOLUME=$4
6+
7+
# Reference: https://forums.docker.com/t/how-to-filter-docker-ps-by-exact-name/2880/3
8+
9+
if [[ ! $(docker network ls --filter name=^/$NETWORK$) ]]; then
10+
docker network create $NETWORK
11+
echo network jenkins ${$NETWORK}
12+
fi
13+
14+
if [[ ! $(docker volume ls --filter name=^/$CERTS_VOLUME$) ]]; then
15+
docker volume create $CERTS_VOLUME
16+
echo jenkins certs "$CERTS_VOLUME"
17+
fi
18+
19+
if [[ ! $(docker volume ls --filter name=^/$DATA_VOLUME$) ]]; then
20+
docker volume create $DATA_VOLUME
21+
echo jenkins data "$DATA_VOLUME"
22+
fi
23+
24+
# StartDocker in Docker into jenkins network
25+
docker container run --name jenkins-docker --rm --detach \
26+
--privileged --network jenkins --network-alias docker \
27+
--env DOCKER_TLS_CERTDIR=/certs \
28+
--volume "$CERTS_VOLUME":/certs/client \
29+
--volume "$DATA_VOLUME":/var/jenkins_home \
30+
--publish 2376:2376 docker:dind
31+
32+
# Start Jenkins in the same network
33+
docker container run --name jenkins-blueocean --rm --detach \
34+
--network jenkins --env DOCKER_HOST=tcp://docker:2376 \
35+
--env DOCKER_CERT_PATH=/certs/client --env DOCKER_TLS_VERIFY=1 \
36+
--volume "$DATA_VOLUME":/var/jenkins_home \
37+
--volume "$CERTS_VOLUME":/certs/client:ro \
38+
--publish 8080:8080 --publish 50000:50000 "$IMAGE"
39+
40+
# Ensure that script have permissions to be executed: chmod +x start_jenkins.sh
41+
# Build image from Dockerfile: docker build -t lemoncode/jenkins .
42+
# From previous image we can run custom Jenkins version as follows:
43+
# ./start_jenkins.sh lemoncode/jenkins jenkins jenkins-docker-certs jenkins-data
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# Creando y ejecutando Pipelines simples
2+
3+
## 1.1 Crear una pipeline simple
4+
5+
Log in Jenkins en http://localhost:8080 con `lemoncode`/`lemoncode`.
6+
7+
- New item, pipeline, `demo1-1`
8+
- Select sample pipeline script
9+
- Replace echo with `echo "This is build number $BUILD_NUMBER"`
10+
- Run and check output
11+
12+
```groovy
13+
pipeline {
14+
agent any
15+
16+
stages {
17+
stage('Hello') {
18+
steps {
19+
echo "This is build number $BUILD_NUMBER"
20+
}
21+
}
22+
}
23+
}
24+
```
25+
26+
27+
Si hacemos click en los `logs` podemos encontrar la salida de cada `stage`, el número viene de **$BUILD_NUMBER**, la cual es una variable de entorno que nos provee `Jenkins`.
28+
29+
Como es la primera vez que ejecutamos algo dentro del servidor de Jenkins obtenemos la siguiente salida:
30+
31+
```
32+
Started by user Jaime salas
33+
Running in Durability level: MAX_SURVIVABILITY
34+
[Pipeline] Start of Pipeline
35+
[Pipeline] echo
36+
This is build number 1
37+
[Pipeline] End of Pipeline
38+
[Checks API] No suitable checks publisher found.
39+
Finished: SUCCESS
40+
```
41+
42+
## 1.2 Crear una pipeline simple desde Bitbucket
43+
44+
* Crear un nuevo repositorio en Bitbucket `demo1-2`
45+
46+
Navegamos a http://localhost:8080/blue
47+
48+
- New pipeline `demo1-2`
49+
- Bitbucket repo - git clone https://jaimesalas@bitbucket.org/jaimesalas/demo1-2.git
50+
- Log in with Bitbucket creds
51+
52+
> Needs write access to repo
53+
54+
- Build pipeline
55+
- Add environment variable `DEMO=1`
56+
- Add stage
57+
- Add _Print message_ `This is build $BUILD_NUMBER of demo $DEMO`
58+
- Run and check: doesn't interpolate strings
59+
- View Jenkinsfile in repo:editor only uses single quotes
60+
- Replace with shell script `echo "This is build $BUILD_NUMBER of demo $DEMO"`
61+
62+
63+
Jenkins creates the Jenkinsfile into our new repo, we're not going to get the expected result due to use single quotes.
64+
65+
```groovy
66+
pipeline {
67+
agent any
68+
stages {
69+
stage('stage1') {
70+
steps {
71+
echo 'This is the $BUILD_NUMBER of demo $DEMO'
72+
}
73+
}
74+
75+
}
76+
environment {
77+
DEMO = '1'
78+
}
79+
}
80+
```
81+
82+
We add a new step, bash scripting in this case, and commit the new change to master
83+
84+
```groovy
85+
pipeline {
86+
agent any
87+
stages {
88+
stage('stage1') {
89+
steps {
90+
echo 'This is the $BUILD_NUMBER of demo $DEMO'
91+
sh 'echo "This is build $BUILD_NUMBER of demo $DEMO"'
92+
}
93+
}
94+
95+
}
96+
environment {
97+
DEMO = '1'
98+
}
99+
}
100+
```
101+
102+
## 1.3 Crear una Pipeline desde Git
103+
104+
1. Create a new repository on GitHub
105+
2. Add to source control the following code
106+
107+
**./test.sh**
108+
109+
```bash
110+
#!/bin/sh
111+
echo "Inside the script, demo $DEMO"
112+
```
113+
114+
**Jenkinsfile**
115+
116+
```groovy
117+
pipeline {
118+
agent any
119+
120+
environment {
121+
DEMO='1.3'
122+
}
123+
124+
stages {
125+
stage('stage-1') {
126+
steps {
127+
echo "This is the build number $BUILD_NUMBER of demo $DEMO"
128+
sh '''
129+
echo "Using a multi-line shell step"
130+
chmod +x test.sh
131+
./test.sh
132+
'''
133+
}
134+
}
135+
}
136+
}
137+
```
138+
139+
Back in the classic UI http://localhost:8080
140+
141+
- New item, pipeline, `demo1-3`
142+
- Select pipeline from source control
143+
- Git - https://github.com/JaimeSalas/jenkins-pipeline-demos
144+
- Ensure that the source control branch is **main**
145+
146+
> Walk through the [Jenkinsfile](./1.3/Jenkinsfile)
147+
148+
- Run and check
149+
- Open in blue ocean
150+
- Repeat stage

0 commit comments

Comments
 (0)