From b7b834dc9117a77f53e8e6a77f220236291be77d Mon Sep 17 00:00:00 2001 From: David Maxson Date: Mon, 12 Sep 2022 11:45:06 -0700 Subject: [PATCH] Add example code --- README.md | 9 ++++- docker_printer/cli.py | 14 ++++++- examples/fastapi_app/Dockerfile.synth | 29 ++++++++++++++ examples/fastapi_app/app/__init__.py | 0 examples/fastapi_app/docker-bake.default.json | 38 +++++++++++++++++++ .../fastapi_app/docker-printer/.gitignore | 2 + .../fastapi_app/docker-printer/builds.yml | 5 +++ .../docker-printer/modules/app-code.yml | 11 ++++++ .../docker-printer/modules/app-deps.yml | 10 +++++ .../docker-printer/modules/base.yml | 13 +++++++ .../fastapi_app/docker-printer/targets.yml | 10 +++++ .../templates/pip-install.Dockerfile.jinja2 | 19 ++++++++++ examples/fastapi_app/requirements.txt | 1 + 13 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 examples/fastapi_app/Dockerfile.synth create mode 100644 examples/fastapi_app/app/__init__.py create mode 100644 examples/fastapi_app/docker-bake.default.json create mode 100644 examples/fastapi_app/docker-printer/.gitignore create mode 100644 examples/fastapi_app/docker-printer/builds.yml create mode 100644 examples/fastapi_app/docker-printer/modules/app-code.yml create mode 100644 examples/fastapi_app/docker-printer/modules/app-deps.yml create mode 100644 examples/fastapi_app/docker-printer/modules/base.yml create mode 100644 examples/fastapi_app/docker-printer/targets.yml create mode 100644 examples/fastapi_app/docker-printer/templates/pip-install.Dockerfile.jinja2 create mode 100644 examples/fastapi_app/requirements.txt diff --git a/README.md b/README.md index 64585a6..6074e37 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Documentation Status](https://readthedocs.org/projects/docker-printer/badge/?version=latest)](https://docker-printer.readthedocs.io/en/latest/?badge=latest) +[![Documentation Status](https://readthedocs.org/projects/docker-printer/badge/?version=latest)](https://docker-printer.readthedocs.io/en/latest/?badge=latest) ![PyPI](https://img.shields.io/pypi/v/docker-printer) # Docker-Printer @@ -12,4 +12,11 @@ Regular multi-stage dockerfiles and `docker build` commands are incredibly power # Getting Started and Documentation +``` +pip install docker-printer +docker-printer init +``` + See the [documentation](https://docker-printer.readthedocs.io/en/latest/#) for how to get started. + +There are also example docker constructs provided in the `/examples` folder. diff --git a/docker_printer/cli.py b/docker_printer/cli.py index 83c645c..10e6738 100644 --- a/docker_printer/cli.py +++ b/docker_printer/cli.py @@ -1,4 +1,6 @@ import subprocess +import textwrap +from pathlib import Path import click @@ -61,8 +63,9 @@ def build(name): @cli.command() -def init(): - base_dir = config_dir(default_to_local=True) +@click.argument("path", default=Path(), type=click.Path(exists=True, dir_okay=True)) +def init(path): + base_dir = path / "docker-printer" if base_dir.exists(): click.echo(f"{base_dir} already exists, cannot initialize new project") raise click.Abort() @@ -72,3 +75,10 @@ def init(): (base_dir / "templates").mkdir(exist_ok=False, parents=False) (base_dir / "targets.yml.jinja2").touch(exist_ok=False) (base_dir / "builds.yml.jinja2").touch(exist_ok=False) + (base_dir / ".gitignore").write_text( + textwrap.dedent( + """ + *.rendered.yml + """.lstrip() + ) + ) diff --git a/examples/fastapi_app/Dockerfile.synth b/examples/fastapi_app/Dockerfile.synth new file mode 100644 index 0000000..44425da --- /dev/null +++ b/examples/fastapi_app/Dockerfile.synth @@ -0,0 +1,29 @@ +# syntax = docker/dockerfile:1.2 + +ARG PYTHON_VERSION=3.9 +ARG BASE_OS=slim + +FROM tiangolo/uvicorn-gunicorn-fastapi:python${PYTHON_VERSION}-${BASE_OS} AS base + +ENV APP_DIR="/app" + +RUN mkdir -p ${APP_DIR} +WORKDIR ${APP_DIR} + +FROM base AS dev + +# Install Python dependencies +# Requirement file: ./requirements.txt + +COPY ./requirements.txt ./requirements.txt + +RUN \ + pip install --no-cache-dir -r ./requirements.txt && \ + rm ./requirements.txt + +FROM dev AS prod + +# Add necessary source code into the image for production execution +COPY ./app ${APP_DIR} + +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] diff --git a/examples/fastapi_app/app/__init__.py b/examples/fastapi_app/app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/fastapi_app/docker-bake.default.json b/examples/fastapi_app/docker-bake.default.json new file mode 100644 index 0000000..9f30105 --- /dev/null +++ b/examples/fastapi_app/docker-bake.default.json @@ -0,0 +1,38 @@ +{ + "group": { + "default": { + "targets": [ + "dev", + "prod" + ] + } + }, + "target": { + "dev": { + "dockerfile": "Dockerfile.synth", + "tags": [ + "my_app:dev" + ], + "target": "dev", + "cache-from": [ + "type=docker" + ], + "output": [ + "type=docker" + ] + }, + "prod": { + "dockerfile": "Dockerfile.synth", + "tags": [ + "my_app:prod" + ], + "target": "prod", + "cache-from": [ + "type=docker" + ], + "output": [ + "type=docker" + ] + } + } +} diff --git a/examples/fastapi_app/docker-printer/.gitignore b/examples/fastapi_app/docker-printer/.gitignore new file mode 100644 index 0000000..87c90c0 --- /dev/null +++ b/examples/fastapi_app/docker-printer/.gitignore @@ -0,0 +1,2 @@ + +*.rendered.yml diff --git a/examples/fastapi_app/docker-printer/builds.yml b/examples/fastapi_app/docker-printer/builds.yml new file mode 100644 index 0000000..b814cc3 --- /dev/null +++ b/examples/fastapi_app/docker-printer/builds.yml @@ -0,0 +1,5 @@ +- name: default + image: my_app + build_args: + cache-from: [type=docker] + output: [type=docker] diff --git a/examples/fastapi_app/docker-printer/modules/app-code.yml b/examples/fastapi_app/docker-printer/modules/app-code.yml new file mode 100644 index 0000000..b7821d4 --- /dev/null +++ b/examples/fastapi_app/docker-printer/modules/app-code.yml @@ -0,0 +1,11 @@ +name: app-code +priority: -100 +depends_on: + - base +template: + file: stage.Dockerfile.jinja2 + variables: + instructions: + - "# Add necessary source code into the image for production execution" + - COPY ./app ${APP_DIR} + command: ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] diff --git a/examples/fastapi_app/docker-printer/modules/app-deps.yml b/examples/fastapi_app/docker-printer/modules/app-deps.yml new file mode 100644 index 0000000..bbdb360 --- /dev/null +++ b/examples/fastapi_app/docker-printer/modules/app-deps.yml @@ -0,0 +1,10 @@ +name: app-deps +priority: 70 +depends_on: + - base +template: + file: pip-install.Dockerfile.jinja2 + variables: + requirement_files: + - source: ./requirements.txt + destination: ./requirements.txt diff --git a/examples/fastapi_app/docker-printer/modules/base.yml b/examples/fastapi_app/docker-printer/modules/base.yml new file mode 100644 index 0000000..d86a595 --- /dev/null +++ b/examples/fastapi_app/docker-printer/modules/base.yml @@ -0,0 +1,13 @@ +name: base +priority: 100 +template: + variables: + base: tiangolo/uvicorn-gunicorn-fastapi:python${PYTHON_VERSION}-${BASE_OS} + env: + APP_DIR: /app + instructions: + - RUN mkdir -p ${APP_DIR} + - WORKDIR ${APP_DIR} +image_args: + PYTHON_VERSION: 3.9 + BASE_OS: slim diff --git a/examples/fastapi_app/docker-printer/targets.yml b/examples/fastapi_app/docker-printer/targets.yml new file mode 100644 index 0000000..45b7277 --- /dev/null +++ b/examples/fastapi_app/docker-printer/targets.yml @@ -0,0 +1,10 @@ +- name: dev + modules: + - base + - app-deps + +- name: prod + extends: + - dev + modules: + - app-code diff --git a/examples/fastapi_app/docker-printer/templates/pip-install.Dockerfile.jinja2 b/examples/fastapi_app/docker-printer/templates/pip-install.Dockerfile.jinja2 new file mode 100644 index 0000000..bf49c77 --- /dev/null +++ b/examples/fastapi_app/docker-printer/templates/pip-install.Dockerfile.jinja2 @@ -0,0 +1,19 @@ +{% extends "stage.Dockerfile.jinja2" %} + +{% block instructions -%} +# Install Python dependencies +{% for req in requirement_files -%} +# Requirement file: {{ req['source'] }} +{%- endfor %} +{% if requirements -%} +# Other requirements: {% for req in requirements -%}{{ req }}{{ ", " if not loop.last else "" }}{% endfor %} +{% endif %} + +{% for req in requirement_files -%} +COPY {{ req['source'] }} {{ req['destination'] }} +{% endfor %} + +RUN {% if cache %}--mount=type=cache,target=/var/cache/pip{% endif %} \ + pip install {% if cache %}--cache-dir /var/cache/pip{% else %}--no-cache-dir{% endif %} {% for req in requirement_files %}-r {{ req['destination'] }}{% endfor %} {% for req in requirements %}{{ req }}{{ " " if not loop.last else "" }}{% endfor %}{% for req in requirement_files %} && \ + rm {{ req['destination'] }}{% endfor %} +{% endblock %} diff --git a/examples/fastapi_app/requirements.txt b/examples/fastapi_app/requirements.txt new file mode 100644 index 0000000..a341a31 --- /dev/null +++ b/examples/fastapi_app/requirements.txt @@ -0,0 +1 @@ +# This is where you would put any additional requirements beyond what's installed in the base docker image