Задача: используя Minikube запустить контейнер с CMS Grav .
Шаги:
собрать Docker образ с NGINX + PHP-FPM и кодом приложения
запушить его в DockerHub
запустить контейнер с приложением в Kubernetes кластере
Установка и запуск Minikube описаны тут>>> .
Проверка Grav
Т.к. эту CMS ещё не использовал — сначала попробуем запустить её вручную, и посмотреть как она стартует.
На Arch для проверки устанавливаем PHP и php-gd
:
sudo pacman -S php
sudo pacman -S php-gd
Используем NGINX + PHP-FPM из DockerHub :
sudo docker pull richarvey/nginx-php-fpm:latest
Качаем сам Grav :
cd /tmp
git clone https://github.com/getgrav/grav.git
cd grav/
Запускаем контейнер, монтируем каталог со скачанным Grav :
sudo docker run -ti -p 80:80 -v /tmp/grav/:/var/www/html richarvey/nginx-php-fpm:latest bash
bash-4.3#
Проверяем файлы и выполняем установку зависимостей:
bash-4.3# cd /var/www/html/
bash-4.3# ls -l
total 248
-rw-r--r-- 1 1000 1000 87315 Jun 12 10:50 CHANGELOG.md
-rw-r--r-- 1 1000 1000 6417 Jun 12 10:50 CONTRIBUTING.md
...
drwxr-xr-x 8 1000 1000 160 Jun 12 10:50 user
drwxr-xr-x 2 1000 1000 160 Jun 12 10:50 webserver-configs
bash-4.3# bin/grav install
Preparing to install vendor dependencies...
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Loading composer repositories with package information
Installing dependencies from lock file
Package operations: 27 installs, 0 updates, 0 removals
- Installing antoligy/dom-string-iterators (v1.0.0): Downloading (100%)
...
- Installing twig/twig (v1.33.2): Downloading (100%)
...
SUCCESS cloned https://github.com/getgrav/grav-theme-antimatter -> /var/www/html/user/themes/antimatter
Запускаем NGINX :
bash-4.3# /start.sh
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Loading composer repositories with package information
Installing dependencies from lock file
Nothing to install or update
Generating autoload files
2017-06-12 10:55:51,000 CRIT Set uid to user 0
2017-06-12 10:55:51,230 INFO RPC interface 'supervisor' initialized
2017-06-12 10:55:51,230 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2017-06-12 10:55:51,231 INFO supervisord started with pid 194
2017-06-12 10:55:52,236 INFO spawned: 'php-fpm' with pid 204
2017-06-12 10:55:52,241 INFO spawned: 'nginx' with pid 205
2017-06-12 10:55:53,724 INFO success: php-fpm entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2017-06-12 10:55:53,724 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
С другой консоли проверяем:
curl localhost
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Home | Grav</title>
<meta name="generator" content="GravCMS" />
<meta name="description" content="Grav is an easy to use, yet powerful, open source flat-file CMS" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="icon" type="image/png" href="/user/themes/antimatter/images/favicon.png" />
<link rel="canonical" href="http://localhost" />
ОК, всё работает — переходим к сборке образа.
Сборка Grav в Docker образ
В будущем сборка будет выполняться в Jenkins , а пока готовим свой репозиторий и Dockerfile
.
Готовим репозиторий:
git clone https://github.com/setevoy2/keygrav.git
Cloning into 'keygrav'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
git clone https://github.com/getgrav/grav.git
Cloning into 'grav'...
remote: Counting objects: 32074, done.
remote: Compressing objects: 100% (55/55), done.
remote: Total 32074 (delta 33), reused 54 (delta 20), pack-reused 31990
Receiving objects: 100% (32074/32074), 10.91 MiB | 213.00 KiB/s, done.
Resolving deltas: 100% (18767/18767), done.
rsync -av --progress grav/ keygrav/ --exclude .git
ls -l keygrav/
total 292
drwxr-xr-x 2 setevoy setevoy 4096 Jun 12 14:00 assets
drwxr-xr-x 2 setevoy setevoy 4096 Jun 12 14:00 backup
drwxr-xr-x 2 setevoy setevoy 4096 Jun 12 14:00 bin
...
drwxr-xr-x 8 setevoy setevoy 4096 Jun 12 14:00 user
drwxr-xr-x 2 setevoy setevoy 4096 Jun 12 14:00 webserver-configs
cd keygrav/
git add -A && git commit -m "grav init"
CMS небольшая:
Поэтому можно весь код собрать прямо в образ, по аналогии со сборкой образов NodeJS .
Устанавливаем зависимости:
Создаём Dockerfile
:
FROM richarvey/nginx-php-fpm
COPY . /var/www/html
EXPOSE 443 80
CMD ["/start.sh"]
Пробуем собрать его:
sudo docker build -t keygrav .
Sending build context to Docker daemon 7.426MB
Step 1/5 : FROM richarvey/nginx-php-fpm
---> d1db840b1d7d
Step 2/5 : COPY . /var/www/html
---> 00b95aff170c
...
Step 5/5 : CMD /start.sh
---> Running in ec169fdc37e5
---> c8c8da1b26b5
Removing intermediate container ec169fdc37e5
Successfully built c8c8da1b26b5
Successfully tagged keygrav:latest
Запускаем:
sudo docker run -ti -p 80:80 keygrav
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Loading composer repositories with package information
Installing dependencies from lock file
Nothing to install or update
Generating autoload files
2017-06-12 12:13:49,649 CRIT Set uid to user 0
2017-06-12 12:13:50,046 INFO RPC interface 'supervisor' initialized
2017-06-12 12:13:50,047 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2017-06-12 12:13:50,047 INFO supervisord started with pid 1
2017-06-12 12:13:51,052 INFO spawned: 'php-fpm' with pid 16
2017-06-12 12:13:51,057 INFO spawned: 'nginx' with pid 17
2017-06-12 12:13:52,582 INFO success: php-fpm entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2017-06-12 12:13:52,582 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
Проверяем:
curl localhost
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Home | Grav</title>
<meta name="generator" content="GravCMS" />
<meta name="description" content="Grav is an easy to use, yet powerful, open source flat-file CMS" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="icon" type="image/png" href="/user/themes/antimatter/images/favicon.png" />
<link rel="canonical" href="http://localhost" />
...
Работает.
Собираем ещё раз, и пушим в DockerHub :
sudo docker build -t setevoy/keygrav .
sudo docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: setevoy
Password:
Login Succeeded
sudo docker push setevoy/keygrav
Последний шаг — создать деплоймент для Kubernetes .
Kubernetes deployment
Создаём deployment файл для K8n :
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: keygrav
spec:
replicas: 1
template:
metadata:
labels:
app: nginx-php-grav
spec:
containers:
- name: keygrav
image: setevoy/keygrav:latest
ports:
- containerPort: 80
Запускаем Minikube :
minikube start
Starting local Kubernetes cluster...
Starting VM...
SSH-ing files into VM...
Setting up certs...
Starting cluster components...
Connecting to cluster...
Setting up kubeconfig...
Kubectl is now configured to use the cluster.
Создаём деплоймент:
kubectl create -f keygrav.yml
deployment "keygrav" created
Проверяем:
kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
keygrav 1 1 1 1 2m
Запускаем сервис:
kubectl expose deployment keygrav --type=NodePort
service "keygrav" exposed
Проверяем:
kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
keygrav 10.0.0.216 <none> 80/TCP 14s
Находим URL (т.к. Kubernetes работает в Virtualbox -е):
minikube service keygrav --url
Waiting, endpoint for service is not ready yet...
http://192.168.99.100:30872
Проверяем:
curl http://192.168.99.100:30872
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Home | Grav</title>
<meta name="generator" content="GravCMS" />
<meta name="description" content="Grav is an easy to use, yet powerful, open source flat-file CMS" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="icon" type="image/png" href="/user/themes/antimatter/images/favicon.png" />
<link rel="canonical" href="http://192.168.99.100" />
Работает.
Jenkins pipeline
И ещё один последний шаг — набросать билд-деплой в Jenkins .
Деплоя не будет, т.к. это Proof of Concept и полноценного кластера Kubernetes нет.
Запускаем EC2, запускаем там Jenkins :
docker run -u root -tid -p 80:8080 -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v /usr/lib/x86_64-linux-gnu/libltdl.so.7.3.0:/usr/lib/x86_64-linux-gnu/libltdl.so.7 ---name jenkins jenkins
Опять таки — это не продакшен решение, workspaces Jenkins -а и все созданные пайплайны после остановки контейнера будут удалены.
Запуск Jenkins с workspaces на отдельном разделе описан в посте Azure: Azure Resource Manager provisioning и Jenkins в Docker .
Создаём джобу:
Создаём билд-файл:
Содержимое файла jenkins.groovy
, с функциями:
#!/usr/bin/env groovy
def dockerBuild () {
stage ('Docker build') {
sh 'apt-get update && apt-get -y install php5 php5-gd php5-curl'
sh '/usr/bin/php5 bin/grav install'
withDockerRegistry(registry: [credentialsId: 'setevoy-docker-hub']){
docker.build("setevoy/keygrav:${env.BUILD_NUMBER}").push()
}
}
}
def kuberDeploy () {
stage ('Deploy') {
/* As this is PoC and we have no Dev/QA/etc environments - deploy wasn't done.
Possible soultions
1:
- update keygrav.yml in repo with new :tag
- copy to the Master host
- kubectl apply -f keygrav.yml
2:
- SSH to the Master host and exec `kubectl set image deployment/keygrav keygrav=setevoy/keygrav:${env.BUILD_NUMBER}`
*/
}
}
return this
И скрипт самого билда keybuild.groovy
:
#!/usr/bin/env groovy
node {
git branch: "${BRANCH}", url: "${BUILDREPOURL}"
def build = load 'ci/jenkins.groovy'
build.dockerBuild()
// build.kuberDeploy()
}
Билдим:
Готово.