feat: add Docker support with Dockerfile, docker-compose, and startup scripts
This commit is contained in:
33
Dockerfile
33
Dockerfile
@@ -1,4 +1,31 @@
|
||||
FROM ubuntu:latest
|
||||
LABEL authors="admin"
|
||||
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS builder
|
||||
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy
|
||||
|
||||
ENTRYPOINT ["top", "-b"]
|
||||
# Disable Python downloads, because we want to use the system interpreter
|
||||
# across both images. If using a managed Python version, it needs to be
|
||||
# copied from the build image into the final image; see `standalone.Dockerfile`
|
||||
# for an example.
|
||||
ENV UV_PYTHON_DOWNLOADS=0
|
||||
|
||||
# Install git
|
||||
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /app
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=bind,source=uv.lock,target=uv.lock \
|
||||
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
||||
uv sync --locked --no-install-project --no-dev
|
||||
COPY . /app
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv sync --locked --no-dev
|
||||
|
||||
# Then, use a final image without uv
|
||||
FROM python:3.13-slim-bookworm
|
||||
# It is important to use the image that matches the builder, as the path to the
|
||||
# Python executable must be the same, e.g., using `python:3.11-slim-bookworm`
|
||||
# will fail.
|
||||
|
||||
# Copy the application from the builder
|
||||
COPY --from=builder --chown=app:app /app /app
|
||||
ENV PATH="/app/.venv/bin:$PATH"
|
||||
WORKDIR /app
|
||||
|
||||
2
build-docker.sh
Executable file
2
build-docker.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
docker build -t git.denco.store/fakz9/sipro-stocks:latest .
|
||||
docker push git.denco.store/fakz9/sipro-stocks:latest
|
||||
94
docker-compose.yml
Normal file
94
docker-compose.yml
Normal file
@@ -0,0 +1,94 @@
|
||||
services:
|
||||
taskiq_worker:
|
||||
image: git.denco.store/fakz9/sipro-stocks:latest
|
||||
container_name: stocks_worker
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
command: [ "sh", "./start_taskiq.sh" ]
|
||||
volumes_from:
|
||||
- tmp
|
||||
volumes:
|
||||
- pg-socket:/run/postgresql
|
||||
networks:
|
||||
- appnet
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
rabbitmq:
|
||||
condition: service_healthy
|
||||
taskiq_scheduler:
|
||||
image: git.denco.store/fakz9/sipro-stocks:latest
|
||||
container_name: stocks_scheduler
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
command: [ "sh", "./start_scheduler.sh" ]
|
||||
volumes_from:
|
||||
- tmp
|
||||
volumes:
|
||||
- pg-socket:/run/postgresql
|
||||
networks:
|
||||
- appnet
|
||||
depends_on:
|
||||
- fastapi
|
||||
fastapi:
|
||||
image: git.denco.store/fakz9/sipro-stocks:latest
|
||||
container_name: stocks_fastapi
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
command: [ "sh", "./start_fastapi.sh" ]
|
||||
volumes_from:
|
||||
- tmp
|
||||
volumes:
|
||||
- pg-socket:/run/postgresql
|
||||
networks:
|
||||
- appnet
|
||||
depends_on:
|
||||
- taskiq_worker
|
||||
ports:
|
||||
- "8000:8000"
|
||||
tmp:
|
||||
image: busybox:latest
|
||||
command: [ "chmod", "-R","777", "/tmp/docker" ]
|
||||
volumes:
|
||||
- /tmp/docker/
|
||||
rabbitmq:
|
||||
image: rabbitmq:latest
|
||||
container_name: stocks_rabbitmq
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
RABBITMQ_DEFAULT_USER: guest
|
||||
RABBITMQ_DEFAULT_PASS: guest
|
||||
RABBITMQ_DEFAULT_VHOST: stocks_vhost
|
||||
networks:
|
||||
- appnet
|
||||
healthcheck:
|
||||
test: [ "CMD", "rabbitmqctl", "status" ]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
redis:
|
||||
image: redis:latest
|
||||
container_name: stocks_redis
|
||||
restart: unless-stopped
|
||||
volumes_from:
|
||||
- tmp
|
||||
environment:
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD}
|
||||
command: [ "redis-server", "--unixsocket","/tmp/docker/redis.sock", "--unixsocketperm", "777", "--requirepass", "${REDIS_PASSWORD}" ]
|
||||
networks:
|
||||
- appnet
|
||||
healthcheck:
|
||||
test: [ "CMD" ,"redis-cli", "ping" ]
|
||||
interval: 5s
|
||||
timeout: 2s
|
||||
retries: 5
|
||||
|
||||
networks:
|
||||
appnet:
|
||||
volumes:
|
||||
pg-socket:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
device: /run/postgresql
|
||||
o: bind
|
||||
1
main.py
1
main.py
@@ -131,3 +131,4 @@ async def get_marketplace_stocks(
|
||||
):
|
||||
updater = StocksUpdater(session)
|
||||
return await updater.get_all_stocks_for_marketplace(int(marketplace_id), only_available)
|
||||
|
||||
|
||||
1
start_fastapi.sh
Executable file
1
start_fastapi.sh
Executable file
@@ -0,0 +1 @@
|
||||
gunicorn -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000 main:app
|
||||
@@ -1,57 +1,11 @@
|
||||
#!/bin/bash
|
||||
ulimit -n 97816
|
||||
|
||||
# Load Redis password from .env file
|
||||
export REDIS_PASSWORD=$(grep -m 1 'REDIS_PASSWORD' .env | cut -d '=' -f2)
|
||||
|
||||
# Color definitions for log messages
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to print log messages with colors
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO] $1${NC}"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING] $1${NC}"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR] $1${NC}"
|
||||
}
|
||||
|
||||
# Start clearing Redis locks
|
||||
log_info "Clearing Redis locks..."
|
||||
|
||||
# Check if Redis password was set correctly
|
||||
if [ -z "$REDIS_PASSWORD" ]; then
|
||||
log_error "REDIS_PASSWORD not set. Please check your .env file."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Deleting keys and getting the total deleted count
|
||||
TOTAL_DELETED_KEYS=$(redis-cli -a "$REDIS_PASSWORD" --scan --pattern '*_lock' 2>/dev/null | \
|
||||
xargs -I {} redis-cli -a "$REDIS_PASSWORD" del {} 2>/dev/null | wc -l)
|
||||
|
||||
# Log the result
|
||||
if [ "$TOTAL_DELETED_KEYS" -gt 0 ]; then
|
||||
log_info "Total deleted keys: $TOTAL_DELETED_KEYS"
|
||||
else
|
||||
log_warning "No keys matched the pattern '*_lock'."
|
||||
fi
|
||||
|
||||
# Clear RabbitMQ queue
|
||||
log_info "Purging RabbitMQ queue 'taskiq' in vhost 'stocks_vhost'..."
|
||||
rabbitmqctl purge_queue -p stocks_vhost taskiq
|
||||
if [ $? -eq 0 ]; then
|
||||
log_info "RabbitMQ queue purged successfully."
|
||||
else
|
||||
log_error "Failed to purge RabbitMQ queue. Please check your RabbitMQ setup."
|
||||
fi
|
||||
|
||||
# Start the Taskiq worker
|
||||
log_info "Starting Taskiq worker..."
|
||||
taskiq worker background:taskiq_broker background.tasks --max-async-task 1000 --max-threadpool-threads 8 --max-prefetch 10000 --workers 1
|
||||
|
||||
Reference in New Issue
Block a user