mirror of
https://github.com/batonogov/learn-devops.git
synced 2025-11-29 00:33:02 +00:00
Add docker (#6)
* Add docker * Update example --------- Co-authored-by: Fedor Batonogov <f.batonogov@yandex.ru>
This commit is contained in:
committed by
GitHub
parent
fab1ba15f3
commit
99088532f2
29
.gitignore
vendored
29
.gitignore
vendored
@@ -47,7 +47,36 @@ terraform.rc
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/ansible
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/go
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=go
|
||||
|
||||
### Go ###
|
||||
# If you prefer the allow list template instead of the deny list, see community template:
|
||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||
#
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
# Go workspace file
|
||||
go.work
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/go
|
||||
|
||||
# Other
|
||||
.vscode
|
||||
.DS_Store
|
||||
ansible/secrets
|
||||
main
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
|
||||
## Структура проекта
|
||||
|
||||
0. [kubeadm](./kubeadm/) - это инструмент для простого и быстрого развёртывания кластера Kubernetes.
|
||||
1. [Docker](./docker/) - **Docker** – это программная платформа для быстрой сборки, отладки и развертывания приложений с помощью **контейнеров**.
|
||||
|
||||
1. [OpenTofu](./opnetofu) — программное обеспечение с **открытым исходным кодом**, используемое для **управления внешними ресурсами** (например, в рамках модели **инфраструктура как код**). Проект Linux Foundation. Пользователи определяют и предоставляют инфраструктуру центра обработки данных с помощью **декларативного языка конфигурации**, известного как HashiCorp Configuration Language (HCL) или JSON.
|
||||
2. [kubeadm](./kubeadm/) - это инструмент для простого и быстрого развёртывания кластера Kubernetes.
|
||||
|
||||
2. [Ansible](./ansible) — система управления конфигурациями, написанная на языке программирования **Python**, с использованием **декларативного языка разметки** для **описания конфигураций**. Применяется для **автоматизации настройки и развёртывания программного обеспечения**.
|
||||
3. [OpenTofu](./opnetofu) — программное обеспечение с **открытым исходным кодом**, используемое для **управления внешними ресурсами** (например, в рамках модели **инфраструктура как код**). Проект Linux Foundation. Пользователи определяют и предоставляют инфраструктуру центра обработки данных с помощью **декларативного языка конфигурации**, известного как HashiCorp Configuration Language (HCL) или JSON.
|
||||
|
||||
4. [Ansible](./ansible) — система управления конфигурациями, написанная на языке программирования **Python**, с использованием **декларативного языка разметки** для **описания конфигураций**. Применяется для **автоматизации настройки и развёртывания программного обеспечения**.
|
||||
|
||||
32
docker/.dockerignore
Normal file
32
docker/.dockerignore
Normal file
@@ -0,0 +1,32 @@
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/go
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=go
|
||||
|
||||
### Go ###
|
||||
# If you prefer the allow list template instead of the deny list, see community template:
|
||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||
#
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
# Go workspace file
|
||||
go.work
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/go
|
||||
|
||||
# Other
|
||||
docker-compose.yaml
|
||||
Dockefile
|
||||
nginx.tmpl
|
||||
19
docker/Dockerfile
Normal file
19
docker/Dockerfile
Normal file
@@ -0,0 +1,19 @@
|
||||
# Используем официальный образ Golang
|
||||
FROM docker.io/library/golang:1.22.2-alpine AS builder
|
||||
# Устанавливаем рабочую директорию
|
||||
WORKDIR /build
|
||||
# Копируем исходный код приложения в контейнер
|
||||
COPY ./ ./
|
||||
RUN CGO_ENABLED=0 go build main.go
|
||||
|
||||
# Отдельный этап сборки для уменьшения размера образа
|
||||
FROM docker.io/library/alpine:3.19.1 AS runner
|
||||
# Устанавливаем рабочую директорию
|
||||
WORKDIR /app
|
||||
# Копируем скомпилированное приложение из предыдущего этапа
|
||||
COPY --from=builder /build/main ./
|
||||
# Запускаем healthcheck, проверяющий доступность веб-сервера на порту 8080
|
||||
HEALTHCHECK --interval=5s --timeout=5s --start-period=3s --retries=3 \
|
||||
CMD wget --quiet --tries=1 --spider http://localhost:8080/ || exit 1
|
||||
# Запускаем приложение при старте контейнера
|
||||
CMD ["./main"]
|
||||
82
docker/README.md
Normal file
82
docker/README.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Docker
|
||||
|
||||
## Описание приложения
|
||||
|
||||
Простой веб сервис написанный на **Go**, возвращающий имя узла.
|
||||
|
||||
Сервис можно запустить несколькими способами.
|
||||
|
||||
### Локальный запуск
|
||||
|
||||
Сборка приложения:
|
||||
|
||||
```sh
|
||||
go build main.go
|
||||
```
|
||||
|
||||
Запуск
|
||||
|
||||
```sh
|
||||
./main
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
Сервер запущен на порту 8080...
|
||||
```
|
||||
|
||||
### Запуск в контейнере
|
||||
|
||||
```sh
|
||||
docker build -t test . && docker run test
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
Сервер запущен на порту 8080...
|
||||
```
|
||||
|
||||
### Запуск при помощи docker compose
|
||||
|
||||
Запуск
|
||||
|
||||
```sh
|
||||
docker compose --profile blue up --wait --remove-orphans --scale web-blue=5
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
✔ Network docker_default Created 0.0s
|
||||
✔ Container docker-nginx-proxy-1 Healthy 0.1s
|
||||
✔ Container docker-web-blue-2 Healthy 0.1s
|
||||
✔ Container docker-web-blue-4 Healthy 0.1s
|
||||
✔ Container docker-web-blue-3 Healthy 0.0s
|
||||
✔ Container docker-web-blue-5 Healthy 0.1s
|
||||
✔ Container docker-web-blue-1 Healthy 0.1s
|
||||
```
|
||||
|
||||
### Сине-зеленое развертывание
|
||||
|
||||
Запуск
|
||||
|
||||
```sh
|
||||
bash ./deploy.sh
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
Список контейнеров
|
||||
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
|
||||
docker-nginx-proxy-1 nginxproxy/nginx-proxy:1.5.1-alpine "/app/docker-entrypo…" nginx-proxy 12 seconds ago Up 5 seconds (healthy) 0.0.0.0:80->80/tcp
|
||||
docker-web-blue-1 docker-web-blue "./main" web-blue 12 seconds ago Up 11 seconds (healthy) 8080/tcp
|
||||
docker-web-blue-2 docker-web-blue "./main" web-blue 12 seconds ago Up 11 seconds (healthy) 8080/tcp
|
||||
docker-web-blue-3 docker-web-blue "./main" web-blue 12 seconds ago Up 11 seconds (healthy) 8080/tcp
|
||||
Журналы запуска web-blue
|
||||
web-blue-2 | Сервер запущен на порту 8080...
|
||||
web-blue-1 | Сервер запущен на порту 8080...
|
||||
web-blue-3 | Сервер запущен на порту 8080...
|
||||
```
|
||||
51
docker/deploy.sh
Normal file
51
docker/deploy.sh
Normal file
@@ -0,0 +1,51 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Эта строка настраивает оболочку так, чтобы она выходила из скрипта при возникновении ошибки в любой команде.
|
||||
# Это помогает обнаружить и обрабатывать ошибки в скрипте.
|
||||
set -e
|
||||
|
||||
# Проверяем состояние контейнера с именем "web-blue", чтобы определить, является ли он "здоровым" (healthy).
|
||||
# Если это так, переменным NEW и OLD присваиваются значения "green" и "blue" соответственно, иначе наоборот.
|
||||
if [ "$(docker compose ps web-blue | grep healthy)" ]
|
||||
then
|
||||
export NEW="green"
|
||||
export OLD="blue"
|
||||
else
|
||||
export NEW="blue"
|
||||
export OLD="green"
|
||||
fi
|
||||
|
||||
# Выводим сообщение о том, какой профиль поднимается в данный момент (значение переменной NEW).
|
||||
echo Поднимаю проект с профилем ${NEW}
|
||||
# Эта команда использует docker-compose для запуска проекта с указанным профилем (значение переменной NEW),
|
||||
# разворачивая контейнеры в фоновом режиме, пересоздавая их, удаляя сиротские контейнеры,
|
||||
# масштабируя сервис "web" на три экземпляра и дожидаясь их запуска.
|
||||
docker compose \
|
||||
--profile ${NEW} \
|
||||
up \
|
||||
--detach \
|
||||
--build \
|
||||
--remove-orphans \
|
||||
--scale web-${NEW}=3 \
|
||||
--wait
|
||||
|
||||
# Эта строка выводит сообщение о том, какие сервисы останавливаются в данный момент (значение переменной OLD).
|
||||
echo Останавливаю сервисы ${OLD}
|
||||
# Эта команда использует docker-compose для остановки сервиса "web" с именем, соответствующим значению переменной OLD.
|
||||
docker compose stop \
|
||||
web-${OLD}
|
||||
|
||||
# Эта строка выводит сообщение о том, какие сервисы удаляются в данный момент (значение переменной OLD).
|
||||
echo Удаляю сервисы ${OLD}
|
||||
# Эта команда использует docker-compose для принудительного удаления сервиса "web" с именем, соответствующим значению переменной OLD.
|
||||
docker compose rm -f \
|
||||
web-${OLD}
|
||||
|
||||
# Эта строка выводит сообщение о выводе списка всех контейнеров.
|
||||
echo Список контейнеров
|
||||
docker compose ps -a
|
||||
|
||||
# Эта команда выводит сообщение о том, что будут выведены журналы запуска для сервиса "web" с именем,
|
||||
# соответствующим значению переменной NEW, и затем выводит эти журналы.
|
||||
echo Журналы запуска web-${NEW}
|
||||
docker compose logs web-${NEW}
|
||||
57
docker/docker-compose.yaml
Normal file
57
docker/docker-compose.yaml
Normal file
@@ -0,0 +1,57 @@
|
||||
services:
|
||||
# Сервис для развертывания приложения с профилем "blue"
|
||||
web-blue: &web
|
||||
build:
|
||||
context: .
|
||||
environment:
|
||||
- VIRTUAL_HOST=web # Виртуальный хост для NGINX
|
||||
- VIRTUAL_PORT=8080 # Виртуальный порт для NGINX
|
||||
expose:
|
||||
- 8080
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "0.5" # Лимитированный доступ к ресурсам CPU
|
||||
memory: 32M # Лимит памяти
|
||||
restart: always # Перезапускать сервис при падении
|
||||
profiles:
|
||||
- blue
|
||||
|
||||
# Сервис для развертывания приложения с профилем "green"
|
||||
web-green:
|
||||
<<: *web # Используем настройки из сервиса web-blue
|
||||
profiles:
|
||||
- green
|
||||
|
||||
# NGINX-прокси
|
||||
nginx-proxy:
|
||||
image: nginxproxy/nginx-proxy:1.5.1-alpine
|
||||
expose:
|
||||
- 80
|
||||
ports:
|
||||
- 80:80 # Проксируем порт 80 на хосте
|
||||
healthcheck:
|
||||
# Периодичность проверки состояния (5 секунд)
|
||||
interval: 5s
|
||||
# Максимальное время ожидания ответа (5 секунд)
|
||||
timeout: 5s
|
||||
# Количество попыток в случае неудачной проверки (5 попыток)
|
||||
retries: 5
|
||||
# Время ожидания перед началом проверок (3 секунды)
|
||||
start_period: 3s
|
||||
# Команда для выполнения теста
|
||||
test: curl -f http://localhost/ || exit 1
|
||||
volumes:
|
||||
# Монтируем сокет Docker
|
||||
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||
# Монтируем шаблон NGINX
|
||||
- ./nginx.tmpl:/app/nginx.tmpl:ro
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.1' # Лимитированный доступ к ресурсам CPU
|
||||
memory: 128M # Лимит памяти
|
||||
restart: always
|
||||
profiles:
|
||||
- blue
|
||||
- green
|
||||
28
docker/main.go
Normal file
28
docker/main.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Обработчик запросов
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
// Получаем имя хоста
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Отправляем имя хоста в ответ
|
||||
fmt.Fprintf(w, "Hostname Hostname: %s\n", hostname)
|
||||
})
|
||||
|
||||
// Запуск веб-сервера на порту 8080
|
||||
fmt.Println("Сервер запущен на порту 8080...")
|
||||
if err := http.ListenAndServe(":8080", nil); err != nil {
|
||||
fmt.Printf("Ошибка запуска сервера: %s\n", err)
|
||||
}
|
||||
}
|
||||
20
docker/nginx.tmpl
Normal file
20
docker/nginx.tmpl
Normal file
@@ -0,0 +1,20 @@
|
||||
{{ range $host, $containers := groupBy $ "Env.VIRTUAL_HOST" }}
|
||||
upstream {{ $host }} {
|
||||
|
||||
{{ range $index, $value := $containers }}
|
||||
{{ with $address := index $value.Addresses 0 }}
|
||||
server {{ $value.Hostname }}:{{ $address.Port }};
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
}
|
||||
|
||||
# конфигурация веб-сервера
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
location / {
|
||||
proxy_pass http://{{ $host }};
|
||||
}
|
||||
}
|
||||
{{ end }}
|
||||
@@ -1,2 +1,2 @@
|
||||
virtual_environment_api_token = "root@pam!for-terraform-provider=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
virtual_environment_endpoint = "https://10.0.70.116:8006/"
|
||||
virtual_environment_endpoint = "https://x.x.x.x:8006/"
|
||||
|
||||
Reference in New Issue
Block a user