В этой статье мы подробно рассмотрим процесс установки и настройки всех необходимых инструментов для эффективной разработки Python-приложений с использованием FastAPI, Docker и Docker Compose. Вы узнаете, как создать изолированную среду для вашего проекта, настроить отладку и обеспечить бесперебойную работу вашего приложения.

1. Установка VSCode

Visual Studio Code (VSCode) — это мощный и популярный редактор кода, который станет вашим основным инструментом разработки.

Загрузка и установка VSCode

  1. Скачайте .deb файл для вашей виртуальной машины с официального сайта: https://code.visualstudio.com/Download

  2. Установите скачанный файл, используя команду в терминале:

    sudo apt install ./<file>.deb

    (Замените <file> на имя скачанного .deb файла.)

Добавление репозитория VSCode (альтернативный метод)

Вы также можете добавить официальный репозиторий VSCode, чтобы получать обновления автоматически:

sudo apt-get install wget gpg
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg
sudo install -D -o root -g root -m 644 packages.microsoft.gpg /etc/apt/keyrings/packages.microsoft.gpg
echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" | sudo tee /etc/apt/sources.list.d/vscode.list > /dev/null
rm -f packages.microsoft.gpg

sudo apt install apt-transport-https
sudo apt update
sudo apt install code # или code-insiders

Установка расширения Python в VSCode

После установки VSCode перейдите в раздел Extensions (расширения) в левой боковой панели. Введите "python" в строке поиска и установите расширение с таким же названием. Это расширение крайне полезно для разработки на Python, предоставляя подсветку синтаксиса, автодополнение и отладку.


2. Проверка и установка Docker

Docker позволяет упаковывать ваше приложение и все его зависимости в изолированные контейнеры, что упрощает развертывание и масштабирование.

Проверка установки Docker

Чтобы проверить, установлен ли Docker, выполните команду:

sudo docker -v

Если Docker не установлен или возникли ошибки, перейдите к следующему шагу.

Удаление конфликтующих пакетов

Перед установкой Docker рекомендуется удалить любые потенциально конфликтующие пакеты:

for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done

Установка официального репозитория Docker

# Добавьте официальный ключ GPG Docker:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Добавьте репозиторий в Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

Установка пакетов Docker

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Проверка успешной установки Docker

Запустите тестовый образ hello-world, чтобы убедиться, что Docker установлен корректно:

sudo docker run hello-world

Настройка Docker без sudo

Чтобы выполнять команды Docker без использования sudo, добавьте текущего пользователя в группу docker:

sudo groupadd docker
sudo usermod -aG docker $USER

После этого перезагрузите вашу виртуальную машину, чтобы изменения вступили в силу.

3. Настройка образа для окружения Python с FastAPI

Теперь, когда VSCode и Docker установлены, мы перейдем к созданию изолированной среды для нашего Python-проекта с использованием FastAPI.

3.1. Инициализация проекта в VSCode

  1. Откройте VSCode.

  2. Создайте новую директорию для вашего проекта. Например, назовите её test.

3.2. Создание requirements.txt

В корневой директории вашего проекта test создайте файл requirements.txt. В этом файле будут перечислены все зависимости вашего Python-приложения:

fastapi
uvicorn
  • FastAPI: Высокопроизводительный веб-фреймворк для создания API на Python.

  • Uvicorn: Высокопроизводительный асинхронный веб-сервер, реализующий спецификацию ASGI. Он используется для запуска асинхронных приложений, таких как те, что созданы с помощью FastAPI.

3.3. Создание файла main.py

Внутри директории test создайте подпапку src, а в ней — файл main.py. Вставьте следующий пример кода FastAPI:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}

3.4. Создание Dockerfile

В корневой директории проекта test создайте файл Dockerfile. Этот файл содержит инструкции для Docker по сборке вашего образа:

FROM python:3.10-slim

WORKDIR /code

COPY ./requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY ./src ./src

CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "80", "--reload"]

#Пояснения к Dockerfile:

  • FROM python:3.10-slim: Docker скачает образ python:3.10-slim с Docker Hub. Этот образ уже включает всё необходимое для работы с Python. Вы можете выбрать любую актуальную версию с Docker Hub.

  • WORKDIR /code: Устанавливает рабочую директорию внутри контейнера как /code. Вы можете назвать её по своему усмотрению.

  • COPY ./requirements.txt ./: Копирует файл requirements.txt из вашей локальной директории в рабочую директорию контейнера.

  • RUN pip install --no-cache-dir -r requirements.txt: Устанавливает все зависимости, перечисленные в requirements.txt.

  • COPY ./src ./src: Копирует содержимое локальной папки src в папку src внутри контейнера.

  • CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "80", "--reload"]: Команда, которая будет выполняться при запуске контейнера. В данном случае запускается uvicorn для обслуживания вашего FastAPI-приложения.

Важно: Разделяйте команды в Dockerfile вертикальными пробелами. Docker умеет кешировать каждый блок команд, что ускоряет пересборку образа при изменениях.

3.5. Сборка образа Docker и запуск контейнера

Находясь в корневой директории проекта test в терминале, выполните следующие команды:

  1. Сборка образа:

    docker build -t fastapi-image .

    (Имя fastapi-image может быть любым.)

  2. Запуск контейнера на основе созданного образа:

    docker run --name fastapi-container -p 80:80 fastapi-image
    • fastapi-container: Имя вашего контейнера.

    • fastapi-image: Имя созданного вами образа.

    • -p 80:80: Перенаправляет порт 80 контейнера на порт 80 вашей локальной машины.

После выполнения команды вы увидите, что uvicorn запустился по адресу http://localhost. Откройте этот адрес в браузере, чтобы увидеть результат работы вашего FastAPI-приложения.

3.6. Управление контейнером

  • Завершение работы приложения: Нажмите Ctrl+C в терминале, где запущен контейнер.

  • Удаление контейнера:

    docker rm fastapi-container
  • Запуск контейнера в фоновом режиме (detached mode):

    docker run --name fastapi-container -p 80:80 -d fastapi-image

    Теперь контейнер будет работать в фоновом режиме, и вы сможете продолжить пользоваться терминалом. Проверьте работу приложения на http://localhost.

3.7. Синхронизация изменений с помощью Volumes

Если вы измените код в main.py на локальной машине, вы не увидите изменений в работающем контейнере, так как файл main.py внутри контейнера не обновился. Для синхронизации изменений используйте Volumes.

Volumes — это механизм в Docker, предназначенный для хранения данных, которые должны сохраняться независимо от жизненного цикла контейнера.

  1. Остановите и удалите текущий контейнер (если он запущен):

    docker stop fastapi-container
    docker rm fastapi-container
  2. Запустите контейнер с Volumes:

    docker run --name fastapi-container -p 80:80 -d -v $(pwd):/code fastapi-image
    • -v $(pwd):/code: Привязывает текущую рабочую директорию вашей локальной машины ($(pwd)) к директории /code внутри контейнера. Теперь любые изменения в файлах на локальной машине будут немедленно отражаться в контейнере.

Теперь, если вы измените содержимое файла main.py и обновите страницу http://local, вы сразу увидите изменения.

3.8. Разработка в VSCode внутри контейнера

Теперь возникла другая проблема: VSCode на локальной машине "не знает" о зависимостях, установленных внутри контейнера (например, FastAPI). Чтобы решить это, мы будем использовать возможности удаленной разработки VSCode.

  1. Установите расширения VSCode: Откройте VSCode на локальной машине и установите следующие расширения:

    • Docker

    • Dev Containers

  2. Подключение к запущенному контейнеру:

    • Убедитесь, что ваш контейнер запущен: docker ps.

    • В левом нижнем углу VSCode нажмите кнопку, похожую на >< (Open a Remote Window).

    • Выберите опцию "Attach to Running Container...".

    • VSCode предложит выбрать запущенный контейнер. Выберите fastapi-container (или как вы его назвали).

  3. Открытие проекта в контейнере:

    • VSCode запустится внутри контейнера. Откройте папку /code (или ту, которую вы указали в WORKDIR Dockerfile).

    • Вы увидите то же содержимое, что и на локальной машине, но с важным отличием: в файле main.py Python больше не будет "ругаться" на отсутствие FastAPI, поскольку он установлен в контейнере.

  4. Установите расширение Python в этом новом, "удаленном" окне VSCode (внутри контейнера), если оно ещё не установлено.

Поздравляем! Теперь вы можете разрабатывать непосредственно внутри вашего Docker-контейнера.

4. Использование Docker Compose

Постоянно вводить длинные команды docker run не очень удобно. Здесь на помощь приходит Docker Compose.

Docker Compose — это инструмент для определения и запуска многоконтейнерных Docker-приложений. Он позволяет описывать инфраструктуру приложения в одном файле (docker-compose.yml) и управлять всеми сервисами как единым целым.

4.1. Установка Docker Compose

sudo curl -L "https://github.com/docker/compose/releases/download/v2.38.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo mv /usr/local/bin/docker-compose /usr/bin/docker-compose
sudo chmod +x /usr/bin/docker-compose

Проверка версии Docker Compose

docker-compose version

Вы должны увидеть версию Docker Compose.

4.2. Настройка docker-compose.yml

  1. Остановите и удалите текущий контейнер (если он запущен):

    docker stop fastapi-container
    docker rm fastapi-container
  2. В корневой директории проекта test создайте файл с именем docker-compose.yml и скопируйте в него следующий код:

    services:
      app:
        build: .
        container_name: python-server
        command: uvicorn src.main:app --host 0.0.0.0 --port 80 --reload
        ports:
          - 80:80
        volumes:
          - .:/code
    • services: Определяет сервисы (контейнеры), из которых состоит ваше приложение.

    • app: Имя вашего сервиса (можно выбрать любое).

    • build: .: Указывает Docker Compose, что нужно собрать образ из текущей директории (где находится Dockerfile).

    • container_name: Присваивает имя контейнеру (python-server).

    • command: Команда, которая будет запущена при старте контейнера.

    • ports: Перенаправляет порты (локальный:контейнер).

    • volumes: Монтирует текущую директорию локальной машины к /code внутри контейнера для синхронизации кода.

4.3. Запуск приложения с Docker Compose

Находясь в корневой директории проекта test в терминале, выполните:

docker-compose up

Docker Compose автоматически соберет образ (если нужно) и запустит контейнер. Проверьте работу приложения на http://localhost:80. Вы увидите, что всё работает, но теперь для запуска понадобилась всего одна команда!

4.4. Остановка приложения с Docker Compose

Чтобы остановить все сервисы, определенные в docker-compose.yml, выполните:

docker-compose down

5. Добавление нового сервиса (Redis) с Docker Compose

Docker Compose значительно упрощает добавление новых сервисов в вашу инфраструктуру. Давайте добавим Redis.

5.1. Обновление docker-compose.yml

Дополните ваш файл docker-compose.yml следующим образом:

services:
  app:
    build: .
    container_name: python-server
    command: uvicorn src.main:app --host 0.0.0.0 --port 80 --reload
    ports:
      - 80:80
    volumes:
      - .:/code
    depends_on:
      - redis # Добавлено: указывает зависимость от сервиса redis

  redis: # Новый сервис для Redis
    image: redis:alpine # Имя образа Redis с Docker Hub
  • depends_on: - redis: Указывает Docker Compose, что сервис app зависит от сервиса redis. Это гарантирует, что Redis будет запущен до app.

  • redis: image: redis:alpine: Определяет новый сервис redis и указывает, какой образ использовать (взятый с Docker Hub).

5.2. Обновление requirements.txt

Добавьте зависимость redis в ваш файл requirements.txt:

fastapi
uvicorn
redis

5.3. Пересборка образа и запуск контейнеров

Теперь пересоберите образ и запустите все сервисы с Docker Compose. Флаг --build заставит Docker Compose пересобрать образ app, а -d запустит контейнеры в фоновом режиме.

docker-compose up --build -d

#5.4. Проверка запущенных контейнеров

Убедитесь, что запустились оба контейнера (python-server и redis:alpine):

docker ps

5.5. Проверка установки Redis в VSCode (внутри контейнера)

  1. Снова подключитесь к контейнеру через VSCode (>< -> "Attach to Running Container..." -> python-server).

  2. Если вы пересобирали образ, вам, возможно, придется переустановить расширение Python в этом "удаленном" окне VSCode.

  3. После установки расширения откройте main.py и попробуйте импортировать Redis:

    import redis

    Если VSCode не подсвечивает эту строку как ошибку, значит, Redis успешно установлен в контейнере, и вы можете его использовать в вашем приложении.

6. Настройка отладки (Debug)

Отладка критически важна для разработки. Давайте настроим отладку вашего Python-приложения внутри контейнера.

  1. Закройте удаленное соединение VSCode (>< -> "Close Remote Connection").

  2. Обновите requirements.txt, добавив библиотеку для отладки:

    fastapi
    uvicorn
    redis
    debugpy
  3. Добавьте порт для отладки в docker-compose.yml:

    services:
      app:
        build: .
        container_name: python-server
        command: uvicorn src.main:app --host 0.0.0.0 --port 80 --reload
        ports:
          - 80:80
          - 5678:5678 # Добавлено: порт для отладки
        volumes:
          - .:/code
        depends_on:
          - redis
    
      redis:
        image: redis:alpine
    • - 5678:5678: Перенаправляет порт 5678 контейнера (который будет использоваться для отладки) на порт 5678 вашей локальной машины.

  4. Пересоберите образ и запустите контейнеры:

    docker-compose up --build -d
  5. Снова подключитесь VSCode к контейнеру (>< -> "Attach to Running Container..." -> python-server).

  6. Внесите изменения в main.py, добавив строки для debugpy:

    from fastapi import FastAPI
    
    app = FastAPI()
    
    import debugpy
    debugpy.listen(("0.0.0.0", 5678)) # Начинаем слушать порт для отладки
    
    @app.get("/")
    def read_root():
        return {"Hello": "привет"}

    VSCode должен определить debugpy без ошибок.

  7. Настройка запуска отладчика в VSCode:

    • Перейдите в раздел Run and Debug (иконка жука) в левой боковой панели VSCode.

    • Если файла launch.json нет, нажмите "create a launch.json file".

    • Выберите "Remote Attach" (или "Python: Remote Attach").

    • Выберите localhost и укажите порт 5678.

    • Файл launch.json будет создан с соответствующими настройками.

  8. Запуск отладчика:

    • Установите точку останова в вашем коде (например, на строке return {"Hello": "привет"}).

    • Нажмите F5 (или кнопку "Start Debugging") в VSCode.

    • Обновите страницу http://localhost:80 в браузере. Вы увидите, что выполнение кода остановилось на вашей точке останова, и вы можете использовать все функции отладчика VSCode.

Теперь ваша среда разработки полностью настроена для эффективной работы с Python-проектами в изолированных Docker-контейнерах, включая удобную отладку!

Комментарии (6)


  1. Ryav
    06.07.2025 15:53

    Создание requirements.txt

    Добро пожаловать в 2025! У нас есть pyproject.toml.

    Непонятно, на кого вообще эта статья рачситана. Кто разрабатывает внутри докер контейнера и чем вас не устраивают venv?


    1. shqiptar
      06.07.2025 15:53

      звон немножко в другом месте. такие системы очень удобны для разработчиков (фронтенд, бекенд) в случае когда у себя на компе надо развернуть всю систему, а ставить чужой стек неохота. например, зачем фронту ставить питон, а питонщику реакт или вуе. кстати,а ты сам при разработке где используешь бд - в докере или нативно?
      я например,для своей команды настроил всё в докерах - и фронт,и бекенд и базы данных.причём благодаря томам фастпишник может писать код у себя в идешке, а результат видеть и в терминале и в браузере. а для фронтов это вообще замечательно - не надо ставить питон. к тому же всё это проксирую в нгинксе по доменам и работаем в https.
      если у тебя есть готовое решение для командной работы - то вперёд, напиши статью, если вещь фирменная - возьмём


    1. danilovmy
      06.07.2025 15:53

      @Ryav 2025, середина. У меня пара сотен проектов, много докер файлов и практически ни одного toml. Или я что-то не то делаю, или не только через pyproject.toml можно вести разработку. Ну, к слову, правда, requrements.txt тоже стало меньше.


      1. shqiptar
        06.07.2025 15:53

        requrements.txt мне на нравтся одним - там нет дерева зависимостей. если я по ошибке поставил какойнибудь пакет,а он за собой потянул ещё несколько, то непонятно, что удалять. вроде uv показывает зависимости, но не уверен,не использовал


  1. shqiptar
    06.07.2025 15:53

    у автора немного сумбурный порядок изложения, но в целом подход нравится. плюсанул. молодец
    из замечаний
    1) docker run --name fastapi-container -p 80:80 -d -v $(pwd):/code fastapi-image что это за извращение? в волумес можешь поместить всю папку с фастапи. и таким образом всё что пишешь в идешке - отражается и в докере - фастапи в контейнере перезагружается, а логи ты видишь в терминале идешки. если у тебя несколько контейнеров, и они засирают терминал, то этой командой docker logs -f <имя контейнера> можешь видеть логи нужного тебе контейнера в текущем времени
    2) для уменьшения объёма контейнера советую в докере установить облегчённую версию питона,поставить на неё зависимости, а потом установить новый образ а зависимости ставить из старого

    FROM python:3.13-slim AS builder

    WORKDIR /install

    RUN apt update && apt install -y build-essential

    COPY requirements.txt .
    RUN pip install --upgrade pip &&
    pip wheel --no-deps --wheel-dir /wheels -r requirements.txt

    RUN useradd -m myuser
    USER myuser

    FROM python:3.13-slim
    ENV PYTHONDONTWRITEBYTECODE=1
    PYTHONUNBUFFERED=1
    WORKDIR /backend

    Добавляем самоподписной сертификат в доверенные

    RUN apt-get install -y ca-certificates &&
    update-ca-certificates

    RUN apt update && apt-get install -y curl grep

    Копируем wheels и устанавливаем зависимости

    COPY --from=builder /wheels /wheels
    COPY requirements.txt .
    RUN pip install --no-deps --no-index --find-links=/wheels -r requirements.txt

    --no-deps: Не устанавливает зависимости пакетов, только те, что перечислены в requirements.txt.

    --no-index: Не использует PyPI или другие индексы , т.е. не будет скачивать пакеты из интернета.

    --find-links=/wheels: Ищет пакеты локально в директории /wheels , где должны лежать .whl (wheel) файлы.

    -r requirements.txt: Указывает список пакетов для установки.

    --no-cache-dir: Отключает кэширование загруженных пакетов. Это может быть полезно, чтобы уменьшить размер образа Docker.

    COPY . .

    ENTRYPOINT ["sh", "-c", "
    if [ "$PROFILE" = "1" ]; then
    python -m cProfile -o output.prof runserver.py;
    else
    uvicorn app.main:app --host 0.0.0.0 --port 8000
    --ssl-keyfile /usr/local/share/ca-certificates/tls.key
    --ssl-certfile /usr/local/share/ca-certificates/tls.crt
    --reload;
    fi"]

    3) не забываем про хеалсчеки, зависимости и порты
    одно из решений
    depends_on:
    db:
    condition: service_healthy
    healthcheck:
    test: [ "CMD", "sh", "-c", "curl -sk https://localhost:8000/health_check/ -o /dev/null -w '%{http_code}' | grep -q '200' || exit 1" ]
    interval: 5s
    timeout: 5s
    retries: 10
    networks:
    devops_mynetwork:
    ipv4_address: 172.20.0.12
    зайди в контейнер и проверь,как отработал хеалсчек
    если тебе не надо открывать порт наружу, используй expose: вместо ports:
    если в контейнере надо внести запись в hosts, то есть extra_hosts:


  1. shqiptar
    06.07.2025 15:53

    может и мне подобную статью забабахать?