Skip to content

Latest commit

 

History

History
619 lines (458 loc) · 16.3 KB

File metadata and controls

619 lines (458 loc) · 16.3 KB

Курс карпова

4.1 Volume, bind mounts

  • bind mount

  • volume

  • tmpfs (не рассматриваем) (оперативка)

  • Volume не зависят от хоста

  • Volume более безопасный вариант (нельзя монтировать любые файлы)

  • Volume находятся в специальном месте (удобно)

  • Volumes привязывают только директории

Volume больше про сохранение данных, а bind mount больше про присоединение файлов.

Путь до волюма в системе: /var/lib/docker/volumes/<volume name>.

Иногда волюмы могут создаваться автоматически неявно с уникальным идетификатором. Например при поднятии yandex/clickhouse-server создаются наявно волюмы. Послу удаления контейнеров эти аолюмы останутся в системе.

Почему создаются анонимные волюмы?

Анонимные волюмы создаются когда в Dockerfile встречается команда VOLUME. В случае с clickhouse это строчка VOLUME [var/lib/clickhouse...].

FROM node:17

COPY script.js /app/script.js

VOLUME [/app/]

CMD ["node", "/app/script.js"]
docker build -t node-volume .
docker compose up -d --rm node-volume

4.2 Копирование файлов в рантайм контейнер

Можно скоприровать файлы с хоста внутрь контейнера. И обратною

docker cp <host_path> <container>:<path>
docker cp ./todo_result/ tg-bot:/app/todo_result/

docker cp <container>:<path> <host_path>
docker cp tg-bot:/app/todo_result/todolist.csv todo_result/todolist.csv

docker volume

docker volume ls    # вывести список волюмов
docker voluem create <volume name>  # создание волюма
docker volum rm <volume name>   # удаление волюма

docker volume prune --force     # удаление неиспользуемых анонимных волюмов
docker volume prune -a --force  # удаление всех неиспользуеых волюмов

Опасность при работе с bind mount

По умолчанию в конейнере суперпользовтель. Поэтому из конетйнера можно получить доступ к файлам, которые доступны руту.

Поэтому лучше монтировать отдельные файлы, а не каталоги, даже если несколько раз приходится писать -v.

И не надо монтировать корень /.

Ещё можно потерять взаимодуйствие с логами, если их создвет контейнер, анпример clickhouse, а у текущего пользовтеля нету прав.

Поэтому можно монтировать в режиме чтения

docker run -v <host_path>:<cont_path>:ro image

или использовать директиву USER в Dockerfile, или указывать пользователя при запуске контейнера:

id -U   # узнаём ид пользователя
docker run --user=1000 image

6. Введение в сети

  • none - полная изоляция контейнера от внешней среды и от хоста

  • host - контейнер сидит в сети хоста

  • bridge - сети куда все контейнеры попадают по-умолчанию 172.17.0.0/16

  • overlay

  • ipvlan

  • macvlan

  • network plugins

  • docker network ls - список сетей

docker run --rm --name temp -d -p 8000:8000 --network=none image - использовать сеть none docker run --net=none image - можно использовать короткое имя net

Даже если будет прокинут порт с сетью none то достучаться до приложеняи через него будет нельзя и порт не будет показан в результатах вывода команды docker ps.

А из контейнера можно выйти в другую сеть? Нет нельзя. У контейнера как будто выключен интернет. Но loopback он же localhost 127.0.0.1 будет работать.

host

При запуске в контейнера в режиме сети хочта можно не пробрасывать порты.

docker run --net=host image

До приложения можно будет достучаться, т.к. все его открытые порты станут доступны на хостовом компьютере.

bridge

Сюда попадают все контейнера по умолчанию.

Можно просмотреть низкоуровневую информацию об объектах докера через docker inspect:

docker inspect bridge
# или
docker network inspect bridge

tcpdump

tcpdump -i <интерфейс> [<протокол>]

# слушаем пинги
sudp tcpdump -i eth0 icmp

ports

Можно прокидывать порты при запуске контейнера с параметром -p.

Также можно прокидывать не только порты, но и связку интерфейса с портом

docker run -p <host port>:<container port> image
# или с сокетом
docker run -p <host interface>:<host port>:<container port> image

В таком случае можно поднять два разных контейнера с разными привязанными сокетами. Т.е. один будет напрмер работать на интерфейсе1:8000, другой на интерфейсе2:8000.

Подключение к сети

Можно контйенер при его запуске

docker run --net network_name image
# или
docker run --network network_name image

Или подключить уже после запуска

docker netwotk connect network_name container

7. Приложение в контейнере

Файл конфигурации nginx

user www-data;
worker_processes 2;

events {
    worker_connections 2048;
}

http {
    map $uri $base {
        ~/(?<file>[^/]*)$ $file;
    }

    server {
        listen 80;
        server_name docker.karpovdns.net www.docker.karpovdns.net;

        location /api {
            proxy_pass http://backend:8000/api;
        }

        location / {
            root /nginx/static;
            try_files /$base /index.html ~404;
        }
    }

    include /etc/nginx/sites-enabled/*.conf;
    include mime.types;
}

MultiStage Build

doc

FROM ... AS <name>

FROM ..
COPY --from=<name> ... ...
FROM node:17 as build
WORKDIR /app/
COPY ./todo-list/package.json .
RUN npm i

COPY ./todo-list/ .
RUN npm run build


# stage 2
FROM nginx:alpine
COPY --from=build /app/dist/index.html /nginx/static/index.html
COPY --from=build /app/dist/static/css /nginx/static/
COPY --from=build /app/dist/static/js /nginx/static/

Чтобы остановиться на определенном этапе (стейдже) в мультистейдж Dockerfile при сборке, используйте флаг --target в команде docker build, указывая имя нужного стейджа как значение, например: docker build --target <имя_стейджа> -t <имя_образа> ., что позволит получить промежуточный образ с артефактами до финальной стадии, как объясняет статья о Dockerfile от Cloud.ru.

nginx

nginx upstream

Docker compose

yaml

import yaml

with open("yaml_file.yaml") as f:
    templates = yaml.safe_load(f)

print(tempaltes)

Пустое значение

#yaml_file.yaml
name:
# { 'name': None }
name: Piter
age: 32
# {'name': 'Piter', 'age': 32}

Ключ-значение

name: Piter Olga
# {'name': 'Piter Olga' }
name:
  Piter
  Olga
# {'name': 'Piter Olga'}

Многострочная запись

name: |
  Piter
  Olga
{'name': 'Piter\nOlga\n'}
name: >
  Piter
  Olga
{'name': 'Piter Olga\n'}

Список

name:
  - Piter
  - Olga
# {'name': ['Piter', 'Olga']}

Список объектов

name:
  - Piter: 32
  - Olga: 28
# {'name': [{'Piter': 32}, {'Olga': 28}]}
name:
  - Piter: 32
    Olga: 28

  - Oleg: 33
    Julia: 31
# {'name': [{'Piter': 32, 'Olga': 28}, {'Max': 33, 'Maya': 31}]}
  • & - якорь
  • * - ссылка на якорь
  • <<: * - слияние ключей по ссылке(<<) и ссылка на якорь

Ссылка на списки.

x-eukaryotes:
    organelles:
        &eu-organelles
        - nucleus
        - mitochondria
        - endoplasmic reticulum
        - Golgi apparatus
        - ribosomes
        - cytoskeleton

human-cells:
    cell-wall: absent
    organelles: *eu-organelles
    examples:
        - Macrophage
        - Hepatocyte

yeasts:
    cell-wall: present
    organelles: *eu-organelles
    examples: 
        - Saccharomyces cerevisiae
        - Komagataella phaffii

А можно преедать ссылку не на список, а на ключ.

x-eukaryotes:
    &eu-organelles
    organelles:
        - nucleus
        - mitochondria
        - endoplasmic reticulum
        - Golgi apparatus
        - ribosomes
        - cytoskeleton

human-cells:
    cell-wall: absent
    <<: *eu-organelles
    examples:
        - Macrophage
        - Hepatocyte

yeasts:
    cell-wall: present
    <<: *eu-organelles
    examples: 
        - Saccharomyces cerevisiae
        - Komagataella phaffii
junior:
  &junior
  position: junior
  salary: 50000


team:
  backend:
    - Peter:
        <<: *junior
    - Olga:
        <<: *junior

Можно делать ссылки на структуры данных, чтобы их не повторять.

x-airflow-common:
  &airflow-common
  environment:
    &airflow-common-env
    AIRFLOW__CORE__EXECUTOR: CeleryExecutor
    AIRFLOW__CORE__FERNET_KEY: ''
  depends_on:
    &airflow-common-depends-on
    redis:
      condition: service_healthy
    postgres:
      condition: service_healthy

services:
    airflow-scheduler:
        <<: *airflow-common
        depends_on:
            <<: *airflow-common-depends-on
    airflow-worker:
        <<: *airflow-common
        environment:
            <<: *airflowcommon-env

apache airflow

ETL: - extract - transform - load

Airflow - планировщик для работы с ETL процессами. Например есть пайплайн для работы с юзерами и каждый вечер нам надо его запускать.

docker compose file

9. Docker compose инструкции

name: todo

services:
    db:
        image: postgres:18
        vol
  • restart -

  • restart_policy

  • replicas - количество контейнеров, которые нужно поднять

    services:
        db:
            deploy:
                replicas: 3
  • depends_on

  • healthcheck

    healthcheck:
        test: ["CMD", "curl", "--fail", "localhost:8000/test"]

10. За пределами контейнеров

10.1 Ansible

Варианты для доставки пет-проектов:

  • scp
  • rsync

Более удобный вариант для загрузки пет проекта:

  • docker push
  • docker pull
  • docker run

Для деплоя на прод еть спец програмы, например Ansible - system configurtion manager. Программа для удаленного управления конфигурации. Описывается структура в виде кода.

  • docker push
  • docker pull
  • ansible playbook

Для Ansible в самом простом случае используются два файла:

  • inventory - место где описываются сервера - на какие сервера надо сходить ansible.
  • playbook.yaml - описывает какие задачи надо выполнить на серверах
ansible-playbook -i ./inventory playbook.yaml

Ансибл также позволяет хранить секреты.

Предположим нам надо хранить и использовать секреты в cicd, но зранить их в открытом виде в credentials.yaml нельзя:

#credentials.yaml
Tokens:
    token_1: 123
    token_2: 234
    token_3: 345

У Ansible есть ansible-vault:

ansible-vault encrypt credentials.yaml

Далее этот файл шифруется заданным паролем и позже его можно будет расшифровать в пайплайне.

ansible-vault decrypt credentials.yaml

или вывести в терминал

ansible-vault view credentials.yaml

10.2 ci/cd

10.3 Kubernetes K8S

alt text

Сущности K8S:

  • Namespaces
  • Pod - минимальная еденица к8с
  • ReplicaSet - абстракция для работы некоторого числа подов
  • Deployment - абстракция для более гибкого поведения подов (обновление, откаты) rolling, recreate. Позволяет указать масштабирование.
  • Services
  • ConfigMaps
  • Ingress
  • Secrets
  • Job
  • CronJob
  • Persistent Volumes
  • ...

miniлube - легкая локальная версия к8с с 1 нодой.

sudo minicube start --vm-driver=none
sudo minikube status
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: frontend

spec:
  replicas: 4
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 50%
      maxUnavailable: 50%
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
        - name: nginx
          image: kcoursedocker/frontend-demo:v1

kubectl - утилита для общения с мастер нодой к8с через cli

список нод

kubectl get nodes
kubectl get podes
# deployments
kubectl get deploy
# replica set
kubectl get rs
# namespaces
kubectl get ns
# запуск
kubectl apply -f deploy.yaml
# удалить все
kubectl delete -f deploy.yaml
# удалить поду
kubetl delete pod <pod name>
# удалить deployment - имя можно взять из метадаты deployment.yaml
kubectl delete deploy <deploy_name>

При удалении поды, к8с может автоматически поднять поду в раска конфигурации, если указано дердать некоторое количество под. За это отвечает абстракция реплика-сет.

Strategy - отвечает за обновления. Для применения обновления достаточно поменять конфигурационный файл и применить команду kubectl apply -f deployment.yaml.

Откат до предыдущей версии выполняется также одной командой.

kubectl rollout undo -f deployment.yaml