250 lines
11 KiB
Go
250 lines
11 KiB
Go
package devopsmodules
|
||
|
||
import (
|
||
"fmt"
|
||
"rubric/utils"
|
||
)
|
||
|
||
var DockerModule = Module{
|
||
Key: "docker",
|
||
Aliases: []string{"d", "container", "podman"},
|
||
Title: "Docker и контейнеры",
|
||
Description: "Образы, контейнеры, Dockerfile, Compose, сети, тома, Podman",
|
||
Run: showDocker,
|
||
}
|
||
|
||
func showDocker() {
|
||
utils.Header("DevOps — Docker и контейнеры")
|
||
|
||
utils.Section("Основные понятия")
|
||
utils.Code(`Image (образ) — неизменяемый шаблон (слои файловой системы)
|
||
Container — запущенный экземпляр образа (изолированный процесс)
|
||
Dockerfile — инструкции для сборки образа
|
||
Registry — хранилище образов (Docker Hub, GHCR, ECR, Harbor)
|
||
Volume — постоянное хранилище данных вне контейнера
|
||
Network — виртуальная сеть между контейнерами
|
||
|
||
Изоляция через технологии ядра Linux:
|
||
- namespaces (PID, net, mnt, uts, ipc, user)
|
||
- cgroups (ограничение ресурсов)
|
||
- Union FS (слоистая файловая система)`)
|
||
|
||
utils.Section("Управление образами")
|
||
utils.Command("docker images", "список образов")
|
||
utils.Command("docker pull nginx:1.25", "скачать образ")
|
||
utils.Command("docker pull nginx:latest", "последняя версия")
|
||
utils.Command("docker push myrepo/myapp:1.0", "отправить в реестр")
|
||
utils.Command("docker build -t myapp:1.0 .", "собрать образ из Dockerfile")
|
||
utils.Command("docker build -t myapp:1.0 -f Dockerfile.prod .", "из другого Dockerfile")
|
||
utils.Command("docker rmi nginx:latest", "удалить образ")
|
||
utils.Command("docker image prune", "удалить неиспользуемые образы")
|
||
utils.Command("docker inspect nginx", "подробная информация об образе")
|
||
utils.Command("docker history nginx", "слои образа")
|
||
utils.Command("docker save myapp:1.0 | gzip > myapp.tar.gz", "экспорт образа")
|
||
utils.Command("docker load < myapp.tar.gz", "импорт образа")
|
||
|
||
utils.Section("Управление контейнерами")
|
||
utils.Command("docker run nginx", "запустить контейнер")
|
||
utils.Command("docker run -d nginx", "в фоне (detached)")
|
||
utils.Command("docker run -d -p 8080:80 --name web nginx", "с портом и именем")
|
||
utils.Command("docker run -it ubuntu bash", "интерактивно с терминалом")
|
||
utils.Command("docker run --rm alpine echo 'hello'", "удалить после остановки")
|
||
fmt.Println()
|
||
utils.Code(`# Часто используемые флаги run:
|
||
-d — фоновый режим
|
||
-p 8080:80 — проброс порта (host:container)
|
||
-P — автоматический проброс всех портов
|
||
--name web — имя контейнера
|
||
-e KEY=value — переменная окружения
|
||
--env-file .env — переменные из файла
|
||
-v /host:/cont — монтирование тома
|
||
--network mynet — подключить к сети
|
||
--restart=always — автоперезапуск
|
||
--rm — удалить контейнер после остановки
|
||
--memory=512m — ограничение RAM
|
||
--cpus=0.5 — ограничение CPU
|
||
-u 1000:1000 — пользователь`)
|
||
|
||
utils.Println(utils.ColorBold + "Жизненный цикл контейнера:" + utils.ColorReset)
|
||
utils.Command("docker ps", "запущенные контейнеры")
|
||
utils.Command("docker ps -a", "все контейнеры включая остановленные")
|
||
utils.Command("docker stop web", "остановить (SIGTERM)")
|
||
utils.Command("docker kill web", "принудительно (SIGKILL)")
|
||
utils.Command("docker start web", "запустить остановленный")
|
||
utils.Command("docker restart web", "перезапустить")
|
||
utils.Command("docker rm web", "удалить остановленный")
|
||
utils.Command("docker rm -f web", "удалить принудительно")
|
||
utils.Command("docker container prune", "удалить все остановленные")
|
||
fmt.Println()
|
||
utils.Println(utils.ColorBold + "Взаимодействие с контейнером:" + utils.ColorReset)
|
||
utils.Command("docker exec -it web bash", "открыть shell в запущенном")
|
||
utils.Command("docker exec web ls /etc/nginx", "выполнить команду")
|
||
utils.Command("docker logs web", "логи контейнера")
|
||
utils.Command("docker logs -f web", "следить за логами")
|
||
utils.Command("docker logs --tail 100 web", "последние 100 строк")
|
||
utils.Command("docker cp web:/etc/nginx/nginx.conf .", "скопировать файл из контейнера")
|
||
utils.Command("docker cp nginx.conf web:/etc/nginx/", "скопировать в контейнер")
|
||
utils.Command("docker stats", "использование ресурсов")
|
||
utils.Command("docker top web", "процессы в контейнере")
|
||
|
||
utils.Section("Dockerfile")
|
||
utils.Code(`# Dockerfile — инструкции сборки образа:
|
||
FROM ubuntu:22.04 # базовый образ
|
||
LABEL maintainer="alice@example.com" # метаданные
|
||
|
||
# Установка зависимостей:
|
||
RUN apt-get update && \
|
||
apt-get install -y python3 python3-pip && \
|
||
rm -rf /var/lib/apt/lists/* # очищаем кэш в том же слое
|
||
|
||
WORKDIR /app # рабочая директория
|
||
COPY requirements.txt . # копировать файлы
|
||
RUN pip install -r requirements.txt # установить зависимости
|
||
COPY . . # копировать код
|
||
|
||
ENV APP_ENV=production # переменные окружения
|
||
EXPOSE 8000 # документировать порт
|
||
VOLUME ["/app/data"] # объявить том
|
||
|
||
USER 1000:1000 # непривилегированный пользователь
|
||
CMD ["python3", "-m", "uvicorn", "main:app", "--host", "0.0.0.0"]`)
|
||
|
||
utils.Code(`# Многоэтапная сборка (multi-stage) — уменьшает итоговый размер:
|
||
FROM golang:1.22 AS builder
|
||
WORKDIR /build
|
||
COPY go.mod go.sum ./
|
||
RUN go mod download
|
||
COPY . .
|
||
RUN CGO_ENABLED=0 go build -o app .
|
||
|
||
FROM alpine:3.19
|
||
RUN apk add --no-cache ca-certificates
|
||
WORKDIR /app
|
||
COPY --from=builder /build/app .
|
||
USER 65534:65534
|
||
CMD ["./app"]`)
|
||
|
||
utils.Note("COPY requirements.txt и pip install ПЕРЕД COPY . — слои кэшируются, сборка быстрее.")
|
||
utils.Note("Всегда указывай конкретный тег образа (не latest) для воспроизводимости.")
|
||
|
||
utils.Section("Тома (Volumes)")
|
||
utils.Code(`Типы хранилища:
|
||
Volume — управляется Docker (/var/lib/docker/volumes/)
|
||
Bind mount — директория хоста, монтируется в контейнер
|
||
tmpfs — только в памяти (временное)
|
||
|
||
# Named volume:
|
||
docker volume create mydata
|
||
docker run -v mydata:/app/data nginx
|
||
docker volume ls
|
||
docker volume inspect mydata
|
||
docker volume rm mydata
|
||
docker volume prune
|
||
|
||
# Bind mount:
|
||
docker run -v /host/path:/container/path nginx
|
||
docker run -v $(pwd):/app nginx # текущая директория
|
||
|
||
# tmpfs:
|
||
docker run --tmpfs /tmp nginx`)
|
||
|
||
utils.Section("Сети (Networks)")
|
||
utils.Code(`Типы сетей:
|
||
bridge — виртуальная сеть по умолчанию (контейнеры изолированы от хоста)
|
||
host — контейнер использует сеть хоста напрямую
|
||
none — без сети
|
||
overlay — между несколькими хостами (Docker Swarm)
|
||
|
||
docker network ls
|
||
docker network create mynet
|
||
docker network create --subnet=172.20.0.0/16 mynet
|
||
docker run --network mynet --name db postgres
|
||
docker run --network mynet --name app myapp # app может обращаться к db по имени!
|
||
docker network connect mynet container1
|
||
docker network disconnect mynet container1
|
||
docker network inspect mynet
|
||
docker network rm mynet`)
|
||
|
||
utils.Section("Docker Compose")
|
||
utils.Code(`# docker-compose.yml — многоконтейнерное приложение:
|
||
version: '3.9'
|
||
|
||
services:
|
||
web:
|
||
build: .
|
||
ports:
|
||
- "8080:8000"
|
||
environment:
|
||
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
|
||
volumes:
|
||
- ./:/app
|
||
depends_on:
|
||
db:
|
||
condition: service_healthy
|
||
restart: unless-stopped
|
||
|
||
db:
|
||
image: postgres:16
|
||
environment:
|
||
POSTGRES_USER: user
|
||
POSTGRES_PASSWORD: pass
|
||
POSTGRES_DB: mydb
|
||
volumes:
|
||
- pgdata:/var/lib/postgresql/data
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "pg_isready -U user"]
|
||
interval: 5s
|
||
timeout: 5s
|
||
retries: 5
|
||
|
||
redis:
|
||
image: redis:7-alpine
|
||
command: redis-server --appendonly yes
|
||
volumes:
|
||
- redisdata:/data
|
||
|
||
volumes:
|
||
pgdata:
|
||
redisdata:
|
||
|
||
networks:
|
||
default:
|
||
name: myapp-network`)
|
||
|
||
utils.Println(utils.ColorBold + "Команды Compose:" + utils.ColorReset)
|
||
utils.Command("docker compose up -d", "запустить все сервисы в фоне")
|
||
utils.Command("docker compose up -d --build", "пересобрать образы")
|
||
utils.Command("docker compose down", "остановить и удалить контейнеры")
|
||
utils.Command("docker compose down -v", "удалить и тома")
|
||
utils.Command("docker compose ps", "статус сервисов")
|
||
utils.Command("docker compose logs -f web", "логи сервиса")
|
||
utils.Command("docker compose exec web bash", "shell в сервисе")
|
||
utils.Command("docker compose restart web", "перезапустить сервис")
|
||
utils.Command("docker compose scale web=3", "масштабировать сервис")
|
||
|
||
utils.Section("Podman — альтернатива без демона")
|
||
utils.Code(`Podman — daemonless, rootless, совместим с Docker CLI.
|
||
Используется в RHEL вместо Docker.
|
||
|
||
# Команды идентичны Docker:
|
||
podman run -d -p 8080:80 nginx
|
||
podman build -t myapp .
|
||
podman ps
|
||
podman images
|
||
|
||
# Rootless-контейнеры (без root):
|
||
podman run --user 1000 nginx
|
||
|
||
# Podman Compose:
|
||
podman-compose up -d
|
||
|
||
# Генерация systemd-юнита для контейнера:
|
||
podman generate systemd --name mycontainer > /etc/systemd/system/mycontainer.service
|
||
|
||
# Podman Pod (группа контейнеров с общей сетью):
|
||
podman pod create --name mypod -p 8080:80
|
||
podman run -d --pod mypod nginx
|
||
podman pod ps`)
|
||
|
||
utils.Footer()
|
||
}
|