mirror of
https://github.com/batonogov/learn-devops.git
synced 2025-11-29 00:33:02 +00:00
Add uv example (#30)
Co-authored-by: Fedor Batonogov <f.batonogov@yandex.ru>
This commit is contained in:
committed by
GitHub
parent
a998a1bfdb
commit
ea0d72d879
@@ -19,7 +19,7 @@ repos:
|
||||
- id: trailing-whitespace
|
||||
|
||||
- repo: https://github.com/ansible-community/ansible-lint.git
|
||||
rev: v24.10.0
|
||||
rev: v24.12.2
|
||||
hooks:
|
||||
- id: ansible-lint
|
||||
exclude: ^talos/
|
||||
@@ -31,8 +31,16 @@ repos:
|
||||
- id: tofu_validate
|
||||
|
||||
- repo: https://github.com/igorshubovych/markdownlint-cli
|
||||
rev: v0.42.0
|
||||
rev: v0.43.0
|
||||
hooks:
|
||||
- id: markdownlint
|
||||
args: ["--fix"]
|
||||
args: [--fix]
|
||||
files: \.md$
|
||||
|
||||
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
|
||||
rev: v2.14.0
|
||||
hooks:
|
||||
- id: pretty-format-yaml
|
||||
args: [--autofix, --indent, '2', --offset, '2']
|
||||
- id: pretty-format-toml
|
||||
args: [--autofix]
|
||||
|
||||
137
docker/README.md
137
docker/README.md
@@ -1,133 +1,20 @@
|
||||
# Docker
|
||||
|
||||
## Описание приложения
|
||||
## Blue-green deployment
|
||||
|
||||
Простой веб сервис написанный на **Go**, возвращающий имя узла.
|
||||
Сине-зеленое развертывание — это стратегия развертывания, при которой вы создаете два отдельных, но идентичные среды.
|
||||
Одна среда (синяя) использует текущую версию приложения и одна среда (зеленая) использует новую версию приложения.
|
||||
Использование синего/зеленого развертывания стратегия повышает доступность приложений
|
||||
и снижает риск развертывания за счет упрощения процесс отката в случае сбоя развертывания.
|
||||
После завершения тестирования на зеленом среда, трафик активных приложений направляется в зеленую среду и синюю среда устарела.
|
||||
|
||||
Сервис можно запустить несколькими способами.
|
||||
[Blue-green deployment](./blue-green-deployment/) - это программная платформа для быстрой сборки, отладки и развертывания приложений с помощью **контейнеров**.
|
||||
|
||||
### Локальный запуск
|
||||
## uv
|
||||
|
||||
Сборка приложения:
|
||||
Чрезвычайно быстрый менеджер пакетов и проектов Python, написанный на Rust.
|
||||
|
||||
```sh
|
||||
go build main.go
|
||||
```
|
||||
Один инструмент для замены **pip**, **pip-tools**, **pipx**, **poetry**, **pyenv**, **twine**, **virtualenv**, и многое другое.
|
||||
|
||||
Запуск
|
||||
|
||||
```sh
|
||||
./main
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
Сервер запущен на порту 8080...
|
||||
```
|
||||
|
||||
Проверка
|
||||
|
||||
```sh
|
||||
curl localhost:8080
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
Имя узла: MacBook-Pro-Fedor.local
|
||||
```
|
||||
|
||||
### Запуск в контейнере
|
||||
|
||||
```sh
|
||||
docker build -t test . && docker run --hostname my_container --publish 8080:8080 test
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
Сервер запущен на порту 8080...
|
||||
```
|
||||
|
||||
Проверка
|
||||
|
||||
```sh
|
||||
curl localhost:8080
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
Имя узла: my_container
|
||||
```
|
||||
|
||||
### Запуск при помощи docker compose
|
||||
|
||||
Запуск
|
||||
|
||||
```sh
|
||||
docker compose --profile blue up --wait --remove-orphans --scale web-blue=3
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
✔ Network docker_default Created
|
||||
✔ Container docker-web-blue-1 Healthy
|
||||
✔ Container docker-nginx-proxy-1 Healthy
|
||||
✔ Container docker-web-blue-3 Healthy
|
||||
✔ Container docker-web-blue-2 Healthy
|
||||
```
|
||||
|
||||
Проверка
|
||||
|
||||
Поскольку запущено несколько реплик сервиса, то при повторной проверке мы можем увидеть разное имена узлов
|
||||
|
||||
```sh
|
||||
declare -A responses
|
||||
count=0
|
||||
|
||||
while [ ${#responses[@]} -lt 3 ]; do
|
||||
response=$(curl -s localhost:8080)
|
||||
|
||||
if [[ -z "${responses[$response]}" ]]; then
|
||||
responses["$response"]=1
|
||||
count=$((count + 1))
|
||||
echo "Уникальный ответ $count: $response"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
Уникальный ответ 1: Имя узла: eeec60605b3c
|
||||
Уникальный ответ 2: Имя узла: 1a0e8d8f0d64
|
||||
Уникальный ответ 3: Имя узла: d5822762eab6
|
||||
```
|
||||
|
||||
### Сине-зеленое развертывание
|
||||
|
||||
Запуск
|
||||
|
||||
```sh
|
||||
bash ./deploy.sh
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
Список контейнеров
|
||||
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
|
||||
docker-nginx-proxy-1 nginxproxy/nginx-proxy:1.6.2-alpine "/app/docker-entrypo…" nginx-proxy 22 seconds ago Up 22 seconds (healthy) 0.0.0.0:80->80/tcp
|
||||
docker-web-green-1 docker-web-green "./main" web-green 6 seconds ago Up 6 seconds (healthy) 8080/tcp
|
||||
docker-web-green-2 docker-web-green "./main" web-green 6 seconds ago Up 6 seconds (healthy) 8080/tcp
|
||||
docker-web-green-3 docker-web-green "./main" web-green 6 seconds ago Up 6 seconds (healthy) 8080/tcp
|
||||
Журналы запуска web-green
|
||||
web-green-3 | Сервер запущен на порту 8080...
|
||||
web-green-2 | Сервер запущен на порту 8080...
|
||||
web-green-1 | Сервер запущен на порту 8080...
|
||||
```
|
||||
|
||||
[Проверка](README.md#L83)
|
||||
[uv](./uv/)
|
||||
[Официальный GitHub репозиторий](https://github.com/astral-sh/uv)
|
||||
|
||||
133
docker/blue-green-deployment/README.md
Normal file
133
docker/blue-green-deployment/README.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# Docker
|
||||
|
||||
## Описание приложения
|
||||
|
||||
Простой веб сервис написанный на **Go**, возвращающий имя узла.
|
||||
|
||||
Сервис можно запустить несколькими способами.
|
||||
|
||||
### Локальный запуск
|
||||
|
||||
Сборка приложения:
|
||||
|
||||
```sh
|
||||
go build main.go
|
||||
```
|
||||
|
||||
Запуск
|
||||
|
||||
```sh
|
||||
./main
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
Сервер запущен на порту 8080...
|
||||
```
|
||||
|
||||
Проверка
|
||||
|
||||
```sh
|
||||
curl localhost:8080
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
Имя узла: MacBook-Pro-Fedor.local
|
||||
```
|
||||
|
||||
### Запуск в контейнере
|
||||
|
||||
```sh
|
||||
docker build -t test . && docker run --hostname my_container --publish 8080:8080 test
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
Сервер запущен на порту 8080...
|
||||
```
|
||||
|
||||
Проверка
|
||||
|
||||
```sh
|
||||
curl localhost:8080
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
Имя узла: my_container
|
||||
```
|
||||
|
||||
### Запуск при помощи docker compose
|
||||
|
||||
Запуск
|
||||
|
||||
```sh
|
||||
docker compose --profile blue up --wait --remove-orphans --scale web-blue=3
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
✔ Network docker_default Created
|
||||
✔ Container docker-web-blue-1 Healthy
|
||||
✔ Container docker-nginx-proxy-1 Healthy
|
||||
✔ Container docker-web-blue-3 Healthy
|
||||
✔ Container docker-web-blue-2 Healthy
|
||||
```
|
||||
|
||||
Проверка
|
||||
|
||||
Поскольку запущено несколько реплик сервиса, то при повторной проверке мы можем увидеть разное имена узлов
|
||||
|
||||
```sh
|
||||
declare -A responses
|
||||
count=0
|
||||
|
||||
while [ ${#responses[@]} -lt 3 ]; do
|
||||
response=$(curl -s localhost:8080)
|
||||
|
||||
if [[ -z "${responses[$response]}" ]]; then
|
||||
responses["$response"]=1
|
||||
count=$((count + 1))
|
||||
echo "Уникальный ответ $count: $response"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
Уникальный ответ 1: Имя узла: eeec60605b3c
|
||||
Уникальный ответ 2: Имя узла: 1a0e8d8f0d64
|
||||
Уникальный ответ 3: Имя узла: d5822762eab6
|
||||
```
|
||||
|
||||
### Сине-зеленое развертывание
|
||||
|
||||
Запуск
|
||||
|
||||
```sh
|
||||
bash ./deploy.sh
|
||||
```
|
||||
|
||||
Вывод
|
||||
|
||||
```output
|
||||
Список контейнеров
|
||||
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
|
||||
docker-nginx-proxy-1 nginxproxy/nginx-proxy:1.6.2-alpine "/app/docker-entrypo…" nginx-proxy 22 seconds ago Up 22 seconds (healthy) 0.0.0.0:80->80/tcp
|
||||
docker-web-green-1 docker-web-green "./main" web-green 6 seconds ago Up 6 seconds (healthy) 8080/tcp
|
||||
docker-web-green-2 docker-web-green "./main" web-green 6 seconds ago Up 6 seconds (healthy) 8080/tcp
|
||||
docker-web-green-3 docker-web-green "./main" web-green 6 seconds ago Up 6 seconds (healthy) 8080/tcp
|
||||
Журналы запуска web-green
|
||||
web-green-3 | Сервер запущен на порту 8080...
|
||||
web-green-2 | Сервер запущен на порту 8080...
|
||||
web-green-1 | Сервер запущен на порту 8080...
|
||||
```
|
||||
|
||||
[Проверка](README.md#L83)
|
||||
@@ -11,7 +11,7 @@ services:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "0.5" # Лимитированный доступ к ресурсам CPU
|
||||
cpus: '0.5' # Лимитированный доступ к ресурсам CPU
|
||||
memory: 32M # Лимит памяти
|
||||
restart: always # Перезапускать сервис при падении
|
||||
profiles:
|
||||
@@ -19,7 +19,8 @@ services:
|
||||
|
||||
# Сервис для развертывания приложения с профилем "green"
|
||||
web-green:
|
||||
<<: *web # Используем настройки из сервиса web-blue
|
||||
<<: *web
|
||||
# Используем настройки из сервиса web-blue
|
||||
profiles:
|
||||
- green
|
||||
|
||||
183
docker/uv/.dockerignore
Normal file
183
docker/uv/.dockerignore
Normal file
@@ -0,0 +1,183 @@
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/python
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=python
|
||||
|
||||
### Python ###
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
### Python Patch ###
|
||||
# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
|
||||
poetry.toml
|
||||
|
||||
# ruff
|
||||
.ruff_cache/
|
||||
|
||||
# LSP config files
|
||||
pyrightconfig.json
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/python
|
||||
|
||||
# Other
|
||||
.gitignore
|
||||
Dockerfile*
|
||||
Makefile
|
||||
README.md
|
||||
pyproject.toml
|
||||
176
docker/uv/.gitignore
vendored
Normal file
176
docker/uv/.gitignore
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/python
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=python
|
||||
|
||||
### Python ###
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
### Python Patch ###
|
||||
# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
|
||||
poetry.toml
|
||||
|
||||
# ruff
|
||||
.ruff_cache/
|
||||
|
||||
# LSP config files
|
||||
pyrightconfig.json
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/python
|
||||
43
docker/uv/Dockerfile
Normal file
43
docker/uv/Dockerfile
Normal file
@@ -0,0 +1,43 @@
|
||||
# Базовый образ
|
||||
FROM python:3.13.1-alpine
|
||||
|
||||
# Устанавливаем переменные окружения
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
WORKDIR_PATH="/app" \
|
||||
VENV_PATH="/opt/venv"
|
||||
|
||||
# Определяем аргументы для пользователя и группы
|
||||
ARG USERNAME=appuser
|
||||
ARG GROUPNAME=appgroup
|
||||
|
||||
# Создаем пользователя и рабочую директорию
|
||||
RUN addgroup --system ${GROUPNAME} \
|
||||
&& adduser --system --ingroup ${GROUPNAME} ${USERNAME} \
|
||||
&& mkdir -p ${WORKDIR_PATH} ${VENV_PATH} \
|
||||
&& chown -R ${USERNAME}:${GROUPNAME} ${WORKDIR_PATH} ${VENV_PATH}
|
||||
|
||||
# Устанавливаем рабочую директорию
|
||||
WORKDIR ${WORKDIR_PATH}
|
||||
|
||||
# Копируем uv чрезвычайно быстрый менеджер пакетов и проектов Python
|
||||
COPY --from=ghcr.io/astral-sh/uv:0.5.11 /uv /uvx /bin/
|
||||
|
||||
# Создаем виртуальное окружение и настраиваем PATH
|
||||
RUN uv venv ${VENV_PATH}
|
||||
ENV PATH="${VENV_PATH}/bin:$PATH"
|
||||
|
||||
# Копируем requirements, устанавливаем зависимости в venv и устанавливаем права
|
||||
COPY --chown=${USERNAME}:${GROUPNAME} ./requirements.txt ./requirements.txt
|
||||
RUN uv pip install --no-cache --require-hashes --requirements ./requirements.txt \
|
||||
&& chown -R ${USERNAME}:${GROUPNAME} ${VENV_PATH}
|
||||
|
||||
# Копируем остальные файлы приложения
|
||||
COPY --chown=${USERNAME}:${GROUPNAME} ./ ./
|
||||
|
||||
# Запускаем контейнер от имени нового пользователя
|
||||
USER ${USERNAME}:${GROUPNAME}
|
||||
|
||||
# Настраиваем команду запуска
|
||||
ENTRYPOINT ["uvicorn", "main:app"]
|
||||
CMD [ "--host", "0.0.0.0", "--port", "8000" ]
|
||||
40
docker/uv/Dockerfile.pip
Normal file
40
docker/uv/Dockerfile.pip
Normal file
@@ -0,0 +1,40 @@
|
||||
# Базовый образ
|
||||
FROM python:3.13.1-alpine
|
||||
|
||||
# Устанавливаем переменные окружения
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
WORKDIR_PATH="/app" \
|
||||
VENV_PATH="/opt/venv"
|
||||
|
||||
# Определяем аргументы для пользователя и группы
|
||||
ARG USERNAME=appuser
|
||||
ARG GROUPNAME=appgroup
|
||||
|
||||
# Создаем пользователя и рабочую директорию
|
||||
RUN addgroup --system ${GROUPNAME} \
|
||||
&& adduser --system --ingroup ${GROUPNAME} ${USERNAME} \
|
||||
&& mkdir -p ${WORKDIR_PATH} ${VENV_PATH} \
|
||||
&& chown -R ${USERNAME}:${GROUPNAME} ${WORKDIR_PATH} ${VENV_PATH}
|
||||
|
||||
# Устанавливаем рабочую директорию
|
||||
WORKDIR ${WORKDIR_PATH}
|
||||
|
||||
# Создаем виртуальное окружение и настраиваем PATH
|
||||
RUN python -m venv ${VENV_PATH}
|
||||
ENV PATH="${VENV_PATH}/bin:$PATH"
|
||||
|
||||
# Копируем requirements, устанавливаем зависимости в venv и устанавливаем права
|
||||
COPY --chown=${USERNAME}:${GROUPNAME} ./requirements.txt ./requirements.txt
|
||||
RUN pip install --no-cache --require-hashes -r ./requirements.txt \
|
||||
&& chown -R ${USERNAME}:${GROUPNAME} ${VENV_PATH}
|
||||
|
||||
# Копируем остальные файлы приложения
|
||||
COPY --chown=${USERNAME}:${GROUPNAME} ./ ./
|
||||
|
||||
# Запускаем контейнер от имени нового пользователя
|
||||
USER ${USERNAME}:${GROUPNAME}
|
||||
|
||||
# Настраиваем команду запуска
|
||||
ENTRYPOINT ["uvicorn", "main:app"]
|
||||
CMD [ "--host", "0.0.0.0", "--port", "8000" ]
|
||||
16
docker/uv/Makefile
Normal file
16
docker/uv/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
reqs:
|
||||
rm ./requirements.txt || true
|
||||
uv pip compile --generate-hashes pyproject.toml --output-file ./requirements.txt
|
||||
|
||||
venv:
|
||||
uv venv --python 3.13
|
||||
uv pip install --require-hashes --requirements ./requirements.txt
|
||||
. .venv/bin/activate
|
||||
|
||||
build:
|
||||
time docker build --no-cache --file Dockerfile -t uv .
|
||||
docker images
|
||||
|
||||
build-pip:
|
||||
time docker build --no-cache --file Dockerfile.pip -t pip .
|
||||
docker images
|
||||
37
docker/uv/README.md
Normal file
37
docker/uv/README.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# uv
|
||||
|
||||
Чрезвычайно быстрый менеджер пакетов и проектов Python, написанный на Rust.
|
||||
|
||||
Один инструмент для замены **pip**, **pip-tools**, **pipx**, **poetry**, **pyenv**, **twine**, **virtualenv**, и многое другое.
|
||||
|
||||
[Официальный GitHub репозиторий](https://github.com/astral-sh/uv)
|
||||
|
||||
## Как работаь с **uv**
|
||||
|
||||
[Установка **UV**](https://github.com/astral-sh/uv#installation)
|
||||
|
||||
- Создание окружения
|
||||
|
||||
```sh
|
||||
make venv
|
||||
```
|
||||
|
||||
- Обновление библиотек
|
||||
|
||||
Обноваляем версии зависимостей в **pyproject.toml** и запускаем
|
||||
|
||||
```sh
|
||||
make reqs
|
||||
```
|
||||
|
||||
Сборка образа с **uv** без кэша
|
||||
|
||||
```sh
|
||||
make build
|
||||
```
|
||||
|
||||
Сборка образа с **pip** без кэша
|
||||
|
||||
```sh
|
||||
make build-pip
|
||||
```
|
||||
16
docker/uv/main.py
Normal file
16
docker/uv/main.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
return {"message": "Hello World"}
|
||||
|
||||
@app.post("/items/")
|
||||
async def create_item(item: Item):
|
||||
return item
|
||||
77
docker/uv/pyproject.toml
Normal file
77
docker/uv/pyproject.toml
Normal file
@@ -0,0 +1,77 @@
|
||||
[project]
|
||||
authors = [{name = "Fedor Batonogov", email = "f.batonogov@yandex.ru"}]
|
||||
dependencies = [
|
||||
"aioboto3==13.3.0",
|
||||
"aiobotocore==2.16.0",
|
||||
"aiofiles==24.1.0",
|
||||
"aiohappyeyeballs==2.4.4",
|
||||
"aiohttp==3.11.11",
|
||||
"aioitertools==0.12.0",
|
||||
"aiosignal==1.3.2",
|
||||
"annotated-types==0.7.0",
|
||||
"anyio==4.7.0",
|
||||
"asgi-lifespan==2.1.0",
|
||||
"asyncio==3.4.3",
|
||||
"attrs==24.3.0",
|
||||
"autoflake==2.3.1",
|
||||
"black==24.10.0",
|
||||
"boto3==1.35.81",
|
||||
"botocore==1.35.81",
|
||||
"certifi==2024.12.14",
|
||||
"cfgv==3.4.0",
|
||||
"charset-normalizer==3.4.0",
|
||||
"click==8.1.8",
|
||||
"contextvars==2.4",
|
||||
"distlib==0.3.9",
|
||||
"fastapi==0.115.6",
|
||||
"filelock==3.16.1",
|
||||
"flake8==7.1.1",
|
||||
"frozenlist==1.5.0",
|
||||
"h11==0.14.0",
|
||||
"httpcore==1.0.7",
|
||||
"httpx==0.28.1",
|
||||
"identify==2.6.3",
|
||||
"idna==3.10",
|
||||
"immutables==0.21",
|
||||
"iniconfig==2.0.0",
|
||||
"jmespath==1.0.1",
|
||||
"logging==0.4.9.6",
|
||||
"loguru==0.7.3",
|
||||
"mccabe==0.7.0",
|
||||
"multidict==6.1.0",
|
||||
"multipart==1.2.1",
|
||||
"mypy-extensions==1.0.0",
|
||||
"nodeenv==1.9.1",
|
||||
"packaging==24.2",
|
||||
"pathspec==0.12.1",
|
||||
"platformdirs==4.3.6",
|
||||
"pluggy==1.5.0",
|
||||
"pre_commit==4.0.1",
|
||||
"propcache==0.2.1",
|
||||
"pycodestyle==2.12.1",
|
||||
"pydantic==2.10.4",
|
||||
"pydantic-settings==2.7.0",
|
||||
"pydantic-core==2.27.2",
|
||||
"pyflakes==3.2.0",
|
||||
"pytest==8.3.4",
|
||||
"pytest-asyncio==0.25.0",
|
||||
"pytest-mock==3.14.0",
|
||||
"python-dateutil==2.9.0.post0",
|
||||
"python-dotenv==1.0.1",
|
||||
"python-multipart==0.0.20",
|
||||
"PyYAML==6.0.2",
|
||||
"requests==2.32.3",
|
||||
"s3transfer==0.10.4",
|
||||
"six==1.17.0",
|
||||
"sniffio==1.3.1",
|
||||
"starlette==0.41.3",
|
||||
"typing_extensions==4.12.2",
|
||||
"urllib3==2.3.0 ",
|
||||
"uvicorn==0.34.0",
|
||||
"virtualenv==20.28.0",
|
||||
"wrapt==1.17.0",
|
||||
"yarl==1.18.3"
|
||||
]
|
||||
dynamic = ["version"]
|
||||
name = "uv"
|
||||
requires-python = ">=3.13"
|
||||
1203
docker/uv/requirements.txt
Normal file
1203
docker/uv/requirements.txt
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user