Herkese merhaba!

Uzun yıllardır bol miktarda kişisel zaman ve enerji harcayarak bilgimizi hepinizle paylaşıyoruz. Ancak şu andan itibaren bu blogu çalışır durumda tutabilmek için yardımınıza ihtiyacımız var. Yapmanız gereken tek şey, sitedeki reklamlardan birine tıklamak olacaktır, aksi takdirde hosting vb. masraflar nedeniyle maalesef yayından kaldırılacaktır. Teşekkürler.

Bu örneğimizde dockerli bir uygulamayı Ansible kullanarak CI/CD Jenkins pipeline hattı ile staging sunucusuna iletimini yapacağız. Asıl akış mantığı için aşağıdaki bilgileri okuyunuz.


Jenkins sunucusu için gereksinimler


Aşağıdaki hususlara dikkat ettiğinizden emin olun.



Elimizdeki Jenkins ve Staging bilgileri aşağıdaki gibidir.



Akış mantığı


Jenkins ve GitHub ilişkisi kurulduğu için, GitHub ile bir PR'yi develop brancha eklediğimizde, GitHub Jenkins ile iletişime geçip uygulama iletim işletimini başlatıyor.


  1. Jenkins uygulamayı çeker.

  2. Jenkins docker imajlarını hazırlar.

  3. Jenkins docker imajlarını DockerHub'a iletir.

  4. Jenkins docker artıklarını temizler.

  5. Ansible SSH ile staging sunucusuna bağlanıp uygulama iletim işletimini başlatır.

    1. Uygulama klasörü yaratılır.

    2. Docker dosyaları iletilir.

    3. Uygulama çalıştırılır.

    4. secure-delete paketi kurulur.

    5. İletimi yapılan tüm dosyalar güvenli bir şekilde silinir.

Yapı


.
├── cicd
│   ├── merge
│   │   └── develop
│   │   └── Jenkinsfile
│   └── provision
│      └── stag
│      ├── hosts.yml
│      └── site.yml
├── docker
│   └── stag
│   ├── docker-compose.yml
│   ├── Makefile
│   └── php
│   └── Dockerfile
├── .dockerignore
├── .env
└── src
└── test.php

Dosyalar


cicd/merge/develop/Jenkinsfile


pipeline {
agent any

options {
skipDefaultCheckout(true)
}

stages {
stage('Git') {
steps {
echo '> Checking out the Git version control ...'
checkout scm
}
}
stage('Build') {
steps {
echo '> Building the docker images ...'
sh 'make -sC docker/stag build'
}
}
stage('Push') {
steps {
echo '> Pushing docker images to DockerHub ...'
sh 'make -sC docker/stag push'
}
}
stage('Destroy') {
steps {
echo '> Destroying the docker artifacts ...'
sh 'make -sC docker/stag destroy'
}
}
stage('Deploy') {
steps {
echo '> Deploying the application ...'
sh 'ansible-playbook cicd/provision/stag/site.yml -i cicd/provision/stag/hosts.yml'
}
}
}
}

cicd/provision/stag/hosts.yml


all:
hosts:
staging:
ansible_connection: ssh
ansible_user: vagrant
ansible_host: 192.168.99.30
ansible_port: 22

cicd/provision/stag/site.yml


Docker ve docker-compose programlarını el ile staging sunucusuna kurdum ama aslında bu işlemlerin aşağıda yapılması daha mantıklı olur. Ayrıca aşağıdaki dosya iyileştirmeye açıktır. Mesela değişken kullanmak gibi.


---
# All tasks below are run in "staging" server.

- name: Deploy the application to the "staging" server
hosts: staging
remote_user: vagrant
become: yes
tasks:
- name: Create the application directory
file:
path: /home/vagrant/mini
state: directory
owner: vagrant
group: vagrant
- name: Copy docker files over
copy:
src: ../../../docker/stag/
dest: /home/vagrant/mini/docker/stag
owner: vagrant
group: vagrant
- name: Bring the application up
make:
chdir: /home/vagrant/mini/docker/stag
target: run
- name: Install "secure-delete" package
apt:
name: secure-delete
state: present
- name: Secure deleting application files
command: srm -vzr /home/vagrant/mini

docker/dev/php/Dockerfile


FROM alpine:3.9

RUN apk add --no-cache php7

COPY . /app

WORKDIR /app

RUN rm -rf /var/cache/apk/*

CMD tail -f /dev/null

docker/stag/docker-compose.yml


İmajımız DockerHub'da bulunuyor.


Burada uygulama dosyalarını imaj içine kopyalıyor ve bu şekilde kurulum sonrasında uygulamamızın dosyaları ana sistemde görülmez olacaklar.


version: "3"

services:
mini_php:
build:
context: "../.."
dockerfile: "docker/stag/php/Dockerfile"
image: "inanzzz/mini_php:latest"
env_file:
- "../../.env"

docker/stag/Makefile


build:
@docker-compose build --no-cache

pull:
@docker-compose pull

push:
@docker-compose push

up:
@docker-compose up -d

destroy:
@docker system prune --force --filter 'until=2h'
@docker volume prune --force

run:
@make -s pull up destroy

src/test.php


echo 'success';
echo file_get_contents('./.env');
print_r($_SERVER);
echo getenv('DB_USER').PHP_EOL;
echo getenv('DB_PASS');

.dockerignore


.git/
.idea/
.DS_Store/
.gitignore
.dockerignore
readme.md
docker/
cicd/

.env


DB_USER=root
DB_PASS=password

Test


Mevcut olan PR develop brancha ekleniyor.


Jenkins terminal çıktısı.


Running on Jenkins in /var/lib/jenkins/workspace/mini-merge-develop

[Pipeline] Start of Pipeline
> Checking out the Git version control ...
using GIT_SSH to set credentials
Checking out Revision 11d8e7e0a0584ue4112d4b37ee2f0a2df18abar5 (origin/develop)

> Building the docker images ...
+ make -sC docker/stag build
Successfully built cefb05a3fe90
Successfully tagged inanzzz/mini_php:latest

> Pushing docker images to DockerHub ...
+ make -sC docker/stag push
Pushing mini_php (inanzzz/mini_php:latest)...

> Destroying the docker artefacts ...
+ make -sC docker/stag destroy
Total reclaimed space: 0B

> Deploying the application ...
+ ansible-playbook cicd/provision/stag/site.yml -i cicd/provision/stag/hosts.yml
PLAY [Deploy the application to the "staging" server] **************************

TASK [Gathering Facts] *********************************************************
ok: [staging]

TASK [Create the application directory] ****************************************
changed: [staging]

TASK [Copy docker files over] **************************************************
changed: [staging]

TASK [Bring the application up] ************************************************
changed: [staging]

TASK [Install "secure-delete" package] *****************************************
ok: [staging]

TASK [Secure deleting application files] ***************************************
changed: [staging]

PLAY RECAP *********************************************************************
staging : ok=6 changed=4 unreachable=0 failed=0

[Pipeline] End of Pipeline
Finished: SUCCESS


Staging sunucu kontrolü


Gördüğümüz gibi iletim başlangıcında yaratılan /home/vagrant/mini klasörü, iletim işlemi sonucunda silinmiş durumdalar.


vagrant@staging:~$ ls -l
total 0

Docker bileşenlerini kontrol edelim.


vagrant@staging:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
inanzzz/mini_php latest 3ec65935d03d 6 minutes ago 14.8MB
alpine 3.9 cdf98d1859c1 4 weeks ago 5.53MB

vagrant@staging:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
99ba5891cee3 inanzzz/mini_php:latest "/bin/sh -c 'tail -f…" 7 minutes ago Up 7 minutes stag_mini_php_1

vagrant@staging:~$ docker exec -it stag_mini_php_1 php src/test.php
success
DB_USER=root
DB_PASS=password
Array
(
[HOSTNAME] => e95350a993d9
[SHLVL] => 1
[HOME] => /root
[TERM] => xterm
[PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[DB_PASS] => 123123
[PWD] => /app
[DB_USER] => inanzzz
[PHP_SELF] => src/test.php
[SCRIPT_NAME] => src/test.php
[SCRIPT_FILENAME] => src/test.php
[PATH_TRANSLATED] => src/test.php
[DOCUMENT_ROOT] =>
[REQUEST_TIME_FLOAT] => 1557934232.1256
[REQUEST_TIME] => 1557934232
[argv] => Array
(
[0] => src/test.php
)

[argc] => 1
)
root
password