You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

11 KiB

1. Многоступенчатая сборка образов

1.1.1

FROM mcr.microsoft.com/dotnet/sdk:7.0 AS api_build

WORKDIR /src

COPY ./TodoApi /src

RUN dotnet restore TodoApi.csproj

RUN dotnet build TodoApi.csproj -c Release -o /app/build

FROM api_build AS publish

RUN dotnet publish TodoApi.csproj -c Release -o /app/publish

FROM node:21 AS ui_build

WORKDIR /src

COPY ./todo_ui /src

RUN npm install

RUN npm run build

FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base

WORKDIR /app

COPY --from=publish /app/publish .

COPY --from=ui_build /src/wwwroot ./wwwroot

ENTRYPOINT ["./TodoApi"]

В директории todo_app:

docker build -t todo-bundle .

1.1.2

Создание сети:

docker network create todo

Создание тома для PostgerSQL:

docker volume create todo_pgdata

Запуск PostgreSQL:

docker run -d --name=todo_postgres --network=todo -e POSTGRES_DB=todo -e POSTGRES_USER=todo -e POSTGRES_PASSWORD=todo --mount type=bind,source=./initdb,target=/docker-entrypoint-initdb.d --mount type=volume,source=todo_pgdata,target=/var/lib/postgresql/data postgres:16

1.1.3

docker run --rm -p 8080:80 --name todo_bundle -e 'ConnectionStrings__PostgreSQL=Host=todo_postgres;Port=5432;Database=todo;Username=todo;Password=todo' --name=todo_bundle --network=todo -t todo-bundle

1.2.1

docker container rm -f todo_bundle && docker image rm -f todo-bundle

Докер-файл для API-сервиса

FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build

WORKDIR /src

COPY . /src

RUN dotnet restore TodoApi.csproj

RUN dotnet build TodoApi.csproj -c Release -o /app/build

FROM build AS publish

RUN dotnet publish TodoApi.csproj -c Release -o /app/publish

FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base

WORKDIR /app

COPY --from=publish /app/publish .

ENTRYPOINT ["./TodoApi"]

Сборка образа API-сервиса: (из директории TodoApi)

docker build -t todo-api .

Конфигурация Nginx:

user nginx;
worker_processes auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #gzip  on;

    keepalive_timeout  65;

    server {
        listen 80;

        location / {
            root /var/www/todo;
            index index.html;
            try_files $uri $uri/ /index.html =404;
        }

        location /api {
            proxy_set_header X-Forwarded-Host $http_host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            proxy_buffers 8 64k;
            proxy_busy_buffers_size 128k;
            proxy_buffer_size 64k;

            client_max_body_size 10m;

            proxy_http_version 1.1;
            proxy_pass http://todo_api;
        }
    }
}

Докер-файл для JS-приложения:

FROM node:21 AS ui_build

WORKDIR /build

COPY . /build

RUN npm install

RUN npm run build

FROM nginx AS base

WORKDIR /var/www/todo

COPY --from=ui_build /build/nginx.conf /etc/nginx/nginx.conf

COPY --from=ui_build /build/wwwroot ./

Сборка образа UI: (из директории todo_ui)

docker build -t todo-ui .

1.2.2

Запуск API-сервиса:

docker run -d --name=todo_api --network=todo -e 'ConnectionStrings__PostgreSQL=Host=todo_postgres;Port=5432;Database=todo;Username=todo;Password=todo' todo-api

Запуск UI:

docker run -d -p 8080:80 --name=todo_ui --network=todo todo-ui

1.2.3

FROM mcr.microsoft.com/dotnet/sdk:7.0-bullseye-slim AS build

WORKDIR /src

COPY . /src

RUN dotnet restore TodoApi.csproj

RUN dotnet build TodoApi.csproj -c Release -o /app/build

FROM build AS publish

RUN dotnet publish TodoApi.csproj --self-contained -r linux-x64 -c Release -o /app/publish

FROM debian:bullseye-slim AS base

WORKDIR /app

RUN apt-get update && apt-get install libicu67

COPY --from=publish /app/publish .

ENTRYPOINT ["./TodoApi"]

В директории TodoApi:

docker build -t todo-api .

Запуск, как и выше:

docker run -d --name=todo_api --network=todo -e 'ConnectionStrings__PostgreSQL=Host=todo_postgres;Port=5432;Database=todo;Username=todo;Password=todo' todo-api

2. Политики перезапуска

1.

Добавить в docker run опцию --restart=unless-stopped

2.

docker run -d --name=todo_postgres --network=todo -e POSTGRES_DB=todo -e POSTGRES_USER=todo -e POSTGRES_PASSWORD=todo --mount type=bind,source=./initdb,target=/docker-entrypoint-initdb.d --mount type=volume,source=todo_pgdata,target=/var/lib/postgresql/data --health-cmd='pg_isready -U todo -d todo' --health-interval=10s --health-retries=5 --health-timeout=5s --health-start-period=10s --restart=unless-stopped postgres:16

3. Ограничения ресурсов

1.

Добавить опцию --memory в docker run

2.

Добавить опцию --cpus в docker run

4. Docker compose

1.

docker compose version

https://docs.docker.com/compose/install/linux/

1.

version: '3.9'

services:
  hello:
    image: busybox
    entrypoint: /bin/echo 'Hello, World!'

Запуск, здесь и далее: docker compose up

2.

из директории cats_app из прошлой лабы:

Dockerfile взять из solutions.md оттуда

version: '3.9'

services:
  cats_app:
    container_name: cats_app
    image: cats-app
    build:
      context: ../
      dockerfile: ./cats_app/Dockerfile
    networks:
      - cats
  nginx:
    image: nginx
    container_name: nginx
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - cats_app
    ports:
      - 5000:80
    networks:
      - cats

networks:
  cats:
    driver: bridge

3.

см. ниже

4.

version: '3.9'

services:
  todo_api:
    image: todo-api:latest
    container_name: todo_api
    depends_on:
      - todo_postgres
    build: ./TodoApi
    environment:
      ConnectionStrings__PostgreSQL: "Host=todo_postgres;Port=5432;Database=todo;Username=todo;Password=todo"
      ASPNETCORE_URLS: 'http://*:80'
    restart: unless-stopped
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 500M
    networks:
      - todo
  todo_ui:
    image: todo-ui:latest
    container_name: todo_ui
    depends_on:
      - todo_api
    build: ./todo_ui
    restart: unless-stopped
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 300M
    ports:
      - 8080:80
    networks:
      - todo
  todo_postgres:
    image: postgres:16
    container_name: todo_postgres
    environment:
      POSTGRES_DB: "todo"
      POSTGRES_USER: "todo"
      POSTGRES_PASSWORD: "todo"
      PGDATA: "/var/lib/postgresql/data"
    volumes:
      - ./initdb:/docker-entrypoint-initdb.d
      - todo_pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U todo -d todo"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s
    restart: unless-stopped
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 800M
    networks:
      - todo
  todo_pgadmin:
    container_name: todo_pgadmin
    image: dpage/pgadmin4:7
    depends_on:
      - todo_postgres
    environment:
      PGADMIN_DEFAULT_EMAIL: "todo@example.com"
      PGADMIN_DEFAULT_PASSWORD: "todo"
      PGADMIN_CONFIG_SERVER_MODE: "False"
    volumes:
      - todo_admin_data:/var/lib/pgadmin
    ports:
      - "5050:80"
    restart: unless-stopped
    networks:
      - todo

volumes:
  todo_pgdata:
  todo_admin_data:

networks:
  todo:
    driver: bridge

5. Docker Swarm

1.

docker swarm init

Потом необходимо запомнить токен

2.

docker node ls

3.

docker swarm join-token worker

4.

docker network create -d overlay todo_swarm

5.

docker volume create todo_swarm_pgdata --sharing onewriter

6.

docker service create --name=todo_postgres --replicas 1 --network=todo_swarm -e POSTGRES_DB=todo -e POSTGRES_USER=todo -e POSTGRES_PASSWORD=todo --mount type=bind,source=./initdb,target=/docker-entrypoint-initdb.d --mount type=volume,source=todo_swarm_pgdata,target=/var/lib/postgresql/data --health-cmd='pg_isready -U todo -d todo' --health-interval=10s --health-retries=5 --health-timeout=5s --health-start-period=10s postgres:16

7.

docker service create --name=todo_api --replicas 1 --network=todo_swarm -e 'ConnectionStrings__PostgreSQL=Host=todo_postgres;Port=5432;Database=todo;Username=todo;Password=todo' -e 'ASPNETCORE_URLS=http://*:80' todo-api

8.

docker service create -p 8080:80 --name=todo_ui --replicas 1 --network=todo_swarm todo-ui

9.

Открыть localhost:8080 в браузере

10.

docker service scale todo_ui=3 todo_api=3

11.

docker service ps todo_ui
docker service ps todo_api

12.

docker service logs todo_api

13.

docker service rm todo_api && docker service rm todo_ui && docker service rm todo_postgreq

14

version: '3.9'

services:
  todo_api:
    image: todo-api:latest
    depends_on:
      - todo_postgres
    environment:
      ConnectionStrings__PostgreSQL: "Host=todo_postgres;Port=5432;Database=todo;Username=todo;Password=todo"
      ASPNETCORE_URLS: 'http://*:80'
    deploy:
      mode: replicated
      replicas: 3
      resources:
        limits:
          cpus: '1'
          memory: 500M
    networks:
      - todo
  todo_ui:
    image: todo-ui:latest
    depends_on:
      - todo_api
    deploy:
      mode: replicated
      replicas: 3
      resources:
        limits:
          cpus: '1'
          memory: 300M
    ports:
      - 8080:80
    networks:
      - todo
  todo_postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: "todo"
      POSTGRES_USER: "todo"
      POSTGRES_PASSWORD: "todo"
      PGDATA: "/var/lib/postgresql/data"
    volumes:
      - ./initdb:/docker-entrypoint-initdb.d
      - todo_pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U todo -d todo"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 800M
    networks:
      - todo
  todo_pgadmin:
    image: dpage/pgadmin4:7
    depends_on:
      - todo_postgres
    environment:
      PGADMIN_DEFAULT_EMAIL: "todo@example.com"
      PGADMIN_DEFAULT_PASSWORD: "todo"
      PGADMIN_CONFIG_SERVER_MODE: "False"
    volumes:
      - todo_admin_data:/var/lib/pgadmin
    ports:
      - "5050:80"
    networks:
      - todo

volumes:
  todo_pgdata:
  todo_admin_data:

networks:
  todo:
    driver: overlay

15.

docker stack deploy --compose-file docker-compose.yml