Dockerfile support
parent
999d0e0bfb
commit
8547434c31
@ -0,0 +1,15 @@
|
|||||||
|
./tests
|
||||||
|
./scripts
|
||||||
|
.ruff_cache
|
||||||
|
.coveragerc
|
||||||
|
.dockerignore
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.pre-commit-config.yaml
|
||||||
|
dev-requirements.in
|
||||||
|
dev-requirements.txt
|
||||||
|
pyproject.toml
|
||||||
|
.profile
|
||||||
|
Dockerfile
|
||||||
|
requirements.in
|
||||||
|
tasks.py
|
@ -0,0 +1,55 @@
|
|||||||
|
# syntax = docker/dockerfile:1.4
|
||||||
|
|
||||||
|
# Best practice: Choose a stable base image and tag.
|
||||||
|
FROM python:3.11-slim-bookworm
|
||||||
|
|
||||||
|
# Install security updates, and some useful packages.
|
||||||
|
#
|
||||||
|
# Best practices:
|
||||||
|
# * Make sure apt-get doesn't run in interactive mode.
|
||||||
|
# * Update system packages.
|
||||||
|
# * Pre-install some useful tools.
|
||||||
|
# * Minimize system package installation.
|
||||||
|
RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||||
|
apt-get update && \
|
||||||
|
apt-get -y upgrade && \
|
||||||
|
apt-get install -y --no-install-recommends tini procps net-tools && \
|
||||||
|
apt-get -y clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Install dependencies.
|
||||||
|
#
|
||||||
|
# Best practices:
|
||||||
|
# * `COPY` in files only when needed.
|
||||||
|
# * Reduce disk usage from `pip` installs.
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Create a new user to run as.
|
||||||
|
#
|
||||||
|
# Best practices: Don't run as root.
|
||||||
|
RUN useradd --create-home appuser
|
||||||
|
USER appuser
|
||||||
|
WORKDIR /home/appuser
|
||||||
|
|
||||||
|
# Copy in the code.
|
||||||
|
#
|
||||||
|
# Best practices: Avoid extra chowns.
|
||||||
|
COPY --chown=appuser . .
|
||||||
|
|
||||||
|
# Best practices: Prepare for C crashes.
|
||||||
|
ENV PYTHONFAULTHANDLER=1
|
||||||
|
ENV PYTHONUNBUFFERED=0
|
||||||
|
|
||||||
|
ARG COMMIT_SHA
|
||||||
|
|
||||||
|
LABEL io.runcible.repo-sha="${COMMIT_SHA}"
|
||||||
|
|
||||||
|
# Run the code when the image is run:
|
||||||
|
#
|
||||||
|
# Best practices:
|
||||||
|
# * Add an `init` process.
|
||||||
|
# * Make sure images shut down correctly (via ENTRYPOINT [] syntax).
|
||||||
|
# * '-g' option means killing the container kills all processes, not just the
|
||||||
|
# entrypoint shell.
|
||||||
|
ENTRYPOINT ["tini", "-g", "--", "./entrypoint.sh"]
|
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Best practice: Bash strict mode.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Best practice: Make sure the image shuts down correctly by using `exec` in
|
||||||
|
# entry point shell scripts.
|
||||||
|
exec "$@"
|
@ -0,0 +1,15 @@
|
|||||||
|
from litestar import Litestar
|
||||||
|
from litestar import get
|
||||||
|
|
||||||
|
|
||||||
|
@get("/")
|
||||||
|
async def index() -> str:
|
||||||
|
return "Hello, world!"
|
||||||
|
|
||||||
|
|
||||||
|
@get("/books/{book_id:int}")
|
||||||
|
async def get_book(book_id: int) -> dict[str, int]:
|
||||||
|
return {"book_id": book_id}
|
||||||
|
|
||||||
|
|
||||||
|
app = Litestar([index, get_book])
|
@ -1,5 +0,0 @@
|
|||||||
class Example:
|
|
||||||
"""An example class"""
|
|
||||||
|
|
||||||
def __init__(self, name):
|
|
||||||
self.name = name
|
|
@ -0,0 +1,24 @@
|
|||||||
|
from invoke import task
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def serve(c):
|
||||||
|
"""Serves the speech-collect application locally."""
|
||||||
|
c.run("LITESTAR_APP=speech_collect.app:app litestar run --port 8888 --host 0.0.0.0 --reload")
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def build_image(c, dev=True):
|
||||||
|
"""Builds the speech-collect container image."""
|
||||||
|
context_dir = c.run("pwd", hide=True).stdout.strip()
|
||||||
|
commit_sha = c.run("git rev-parse --short HEAD", hide=True).stdout.strip()
|
||||||
|
c.run(
|
||||||
|
f"docker build --build-arg='COMMIT_SHA={commit_sha}' -t speech-collect:{commit_sha}{'-dev' if dev else ''} {context_dir}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def delint(c):
|
||||||
|
"""Applies automated linters to project"""
|
||||||
|
c.run("isort ./speech_collect ./tests", pty=True)
|
||||||
|
c.run("black ./speech_collect ./tests", pty=True)
|
@ -1,6 +0,0 @@
|
|||||||
from speech_collect.example import Example
|
|
||||||
|
|
||||||
|
|
||||||
def test_example():
|
|
||||||
my_example = Example(name="dirp")
|
|
||||||
assert my_example.name == "dirp"
|
|
Loading…
Reference in New Issue