From cf35530004a2e880b11b38a63ae5e8cd1e13b48c Mon Sep 17 00:00:00 2001 From: Florian Maas Date: Wed, 29 Jun 2022 10:03:25 +0200 Subject: [PATCH] added docker (#41) * added the option to include a simple Dockerfile --- .python-version | 3 --- README.md | 3 ++- cookiecutter.json | 1 + docs/features/docker.md | 23 +++++++++++++++++++ docs/index.md | 1 + docs/prompt_arguments.md | 8 +++++-- hooks/post_gen_project.py | 3 +++ mkdocs.yml | 1 + tests/test_cookiecutter.py | 12 ++++++++++ {{cookiecutter.project_name}}/Dockerfile | 20 ++++++++++++++++ .../{{cookiecutter.project_slug}}/foo.py | 4 ++++ 11 files changed, 73 insertions(+), 6 deletions(-) delete mode 100644 .python-version create mode 100644 docs/features/docker.md create mode 100644 {{cookiecutter.project_name}}/Dockerfile diff --git a/.python-version b/.python-version deleted file mode 100644 index 4f2b6ca..0000000 --- a/.python-version +++ /dev/null @@ -1,3 +0,0 @@ -3.9.7 -3.8.13 -3.7.13 \ No newline at end of file diff --git a/README.md b/README.md index 8743259..abbb80f 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Build status](https://img.shields.io/github/workflow/status/fpgmaas/cookiecutter-poetry/merge-to-main)](https://img.shields.io/github/workflow/status/fpgmaas/cookiecutter-poetry/merge-to-main) [![Supported Python versions](https://img.shields.io/pypi/pyversions/cookiecutter-poetry)](https://pypi.org/project/cookiecutter-poetry/) [![Docs](https://img.shields.io/badge/docs-gh--pages-blue)](https://fpgmaas.github.io/cookiecutter-poetry/) -[![Commit activity](https://img.shields.io/github/commit-activity/m/fpgmaas/cookiecutter-poetry)](https://img.shields.io/github/commit-activity/m/fpgmaas/cookiecutter-poetry) +[![PyPI - Downloads](https://img.shields.io/pypi/dm/cookiecutter-poetry)](https://img.shields.io/pypi/dm/cookiecutter-poetry?style=flat-square) [![License](https://img.shields.io/github/license/fpgmaas/cookiecutter-poetry)](https://img.shields.io/github/license/fpgmaas/cookiecutter-poetry) @@ -27,6 +27,7 @@ repository to generate the file structure for a Python project that uses - Documentation with [MkDocs](https://www.mkdocs.org/) - Static type checking with [mypy](https://mypy.readthedocs.io/en/stable/) - Compatibility testing for multiple versions of Python with [Tox](https://tox.wiki/en/latest/) +- Containerization with [Docker](https://www.docker.com/) ## Example CI/CD Pipeline diff --git a/cookiecutter.json b/cookiecutter.json index ee2a497..aa4eac1 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -10,5 +10,6 @@ "mkdocs": ["y", "n"], "tox": ["y","n"], "mypy" : ["y","n"], + "dockerfile" : ["y","n"], "open_source_license": ["MIT license", "BSD license", "ISC license", "Apache Software License 2.0", "GNU General Public License v3", "Not open source"] } \ No newline at end of file diff --git a/docs/features/docker.md b/docs/features/docker.md new file mode 100644 index 0000000..c1b3ee7 --- /dev/null +++ b/docs/features/docker.md @@ -0,0 +1,23 @@ +# Containerization with Docker + +If `dockerfile` is set to `"y"`, a simple `Dockerfile` is added to the +repository. The Dockerfile installs poetry, sets up the environment and runs +`foo.py` when run. + +The docker image can be built with + +```bash +docker build . -t my-docker-image +``` + +It can then be run in the background with + +```bash +docker run -d my-docker-image +``` + +Or, run it interactive mode with + +``` +docker run --rm -it --entrypoint bash my-docker-image +``` \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index 6321095..4481d0b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -21,6 +21,7 @@ A project generated with ``cookiecutter-poetry`` supports the following features - Documentation with [MkDocs](https://www.mkdocs.org/) - Static type checking with [mypy](https://mypy.readthedocs.io/en/stable/) - Compatibility testing for multiple versions of Python with [Tox](https://tox.wiki/en/latest/) +- Containerization with [Docker](https://www.docker.com/) An example of a repository generated with this package can be found [here](https://github.com/fpgmaas/cookiecutter-poetry-example). diff --git a/docs/prompt_arguments.md b/docs/prompt_arguments.md index beaa7b0..430d713 100644 --- a/docs/prompt_arguments.md +++ b/docs/prompt_arguments.md @@ -58,12 +58,16 @@ will be deployed to the `gh-pages` branch. **tox** -`"y"` or `"n"` Adds automatic [Tox](https://tox.wiki/) testing for +`"y"` or `"n"`. Adds automatic [Tox](https://tox.wiki/) testing for compatibility with multiple versions of Python. **mypy** -`"y"` or `"n"` Adds automatic static type checking with [mypy](https://mypy.readthedocs.io/en/stable/). +`"y"` or `"n"`. Adds automatic static type checking with [mypy](https://mypy.readthedocs.io/en/stable/). + +**dockerfile** + +`"y"` or `"n"`. Adds a simple [Dockerfile](https://docker.com). **open_source_license** diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index d0e7d89..326a7d7 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -20,3 +20,6 @@ def remove_dir(filepath: str) -> None: if "{{cookiecutter.mkdocs}}" != "y": remove_dir("docs") + + if "{{cookiecutter.dockerfile}}" != "y": + remove_file("Dockerfile") diff --git a/mkdocs.yml b/mkdocs.yml index 979b5a0..c3cb66f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -17,6 +17,7 @@ nav: - Documentation with MkDocs: features/mkdocs.md - Compatibility testing with Tox: features/tox.md - Static type checking with mypy: features/mypy.md + - Containerization with Docker: features/docker.md - Tutorial: tutorial.md - Prompt Arguments: prompt_arguments.md plugins: diff --git a/tests/test_cookiecutter.py b/tests/test_cookiecutter.py index 2b261f4..dbecc14 100644 --- a/tests/test_cookiecutter.py +++ b/tests/test_cookiecutter.py @@ -109,3 +109,15 @@ def test_not_tox(cookies, tmp_path): f"{result.project_path}/.github/workflows/on-release-main.yml", "poetry add tox-gh-actions" ) assert not file_contains_text(f"{result.project_path}/tox.ini", "[tox]") + + +def test_dockerfile(cookies, tmp_path): + with run_within_dir(tmp_path): + result = cookies.bake(extra_context={"dockerfile": "y"}) + assert os.path.isfile(f"{result.project_path}/Dockerfile") + + +def test_not_dockerfile(cookies, tmp_path): + with run_within_dir(tmp_path): + result = cookies.bake(extra_context={"dockerfile": "n"}) + assert not os.path.isfile(f"{result.project_path}/Dockerfile") diff --git a/{{cookiecutter.project_name}}/Dockerfile b/{{cookiecutter.project_name}}/Dockerfile new file mode 100644 index 0000000..66088d5 --- /dev/null +++ b/{{cookiecutter.project_name}}/Dockerfile @@ -0,0 +1,20 @@ +# syntax=docker/dockerfile:1 + +FROM python:3.9-slim-buster + +ENV POETRY_VERSION=1.1.13 + +# Install poetry +RUN pip install "poetry==$POETRY_VERSION" + +# Copy only requirements to cache them in docker layer +WORKDIR /code +COPY poetry.lock pyproject.toml /code/ + +# Project initialization: +RUN poetry config virtualenvs.create false && \poetry install --no-interaction --no-ansi --no-root --no-dev + +# Copy Python code to the Docker image +COPY {{cookiecutter.project_slug}} /code/{{cookiecutter.project_slug}}/ + +CMD [ "python", "{{cookiecutter.project_slug}}/foo.py"] \ No newline at end of file diff --git a/{{cookiecutter.project_name}}/{{cookiecutter.project_slug}}/foo.py b/{{cookiecutter.project_name}}/{{cookiecutter.project_slug}}/foo.py index 38b2b52..5e8e64b 100644 --- a/{{cookiecutter.project_name}}/{{cookiecutter.project_slug}}/foo.py +++ b/{{cookiecutter.project_name}}/{{cookiecutter.project_slug}}/foo.py @@ -11,3 +11,7 @@ def foo() -> str: """ return "foo" + + +if __name__ == "__main__": + print(foo())