dcrx


Namedcrx JSON
Version 0.3.4 PyPI version JSON
download
home_pagehttps://github.com/scorbettUM/dcrx
SummaryA library for typesafe, programmatic generation of Docker images via SQL-builder like API.
upload_time2024-01-18 21:34:27
maintainer
docs_urlNone
authorSean Corbett
requires_python>=3.10
license
keywords pypi cicd python setup docker infra devops
VCS
bugtrack_url
requirements pydantic
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # dcrx
[![PyPI version](https://img.shields.io/pypi/v/dcrx?color=gre)](https://pypi.org/project/dcrx/)
[![License](https://img.shields.io/github/license/scorbettUM/dcrx)](https://github.com/scorbettUM/dcrx/blob/main/LICENSE)
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](https://github.com/scorbettUM/dcrx/blob/main/CODE_OF_CONDUCT.md)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/dcrx)](https://pypi.org/project/dcrx/)


DockerX (dcrx) is a library for creating Docker images via an SQL query-builder like API. It is designed to facilitate programmatic, typesafe, and in-memory image generation. dcrx is *not* a wrapper around the Docker CLI or API, nor is it an implementation of these things. Rather, it is designed a lightweight, single-dependency means of writing and creating images that can then be provided to the Docker CLI or SDK for consumption.


# Setup and Install

dcrx is available via PyPi as an installable package. We recommend using Python 3.10+ and a virtual environment. To install dcrx, run:

```bash
python -m venv ~/.dcrx && \
source ~/.dcrx/bin/activate && \
pip install dcrx
```


# Getting Started

dcrx uses a combination of method chaining common to SQL query builder libraries with Pydantic type validation to help you build images with fewer mistakes. As an example, let's create a basic Docker image that echoes "Hello world!" to output upon running the Docker image.

First let's create an empty Python file:

```
touch hello_world.py
```

Open the file and import `Image` from `dcrx`:

```python
from dcrx import Image
```

The Image class is the primary and only interface for generating and working with Docker images in dcrx. Let's go ahead and create an instance:

```python
from dcrx import Image


hello_world = Image("hello-world")
```

Note that we need to provide the name of the image to our class. We can also provide a tag via the `tag` keyword argument if needed (the default is `latest`):

```python
from dcrx import Image

hello_world = Image("hello-world", tag="latest")
```

Next let's call the `stage()` method on our `hello_world` Image instance, passing both the base image name and image tag from which we want to create our image. We'll use `python` as our base image and `3.11-slim` as our tag:

```python
from dcrx import Image

hello_world = Image("hello-world", tag="latest")

hello_world.stage(
    "python",
    "3.11-slim"
)
```

This call translates directly to:

```
FROM python:3.11-slim
```

underneath, just as if you were writing it in the image yourself! You can also use the optional `alias` arg to name the stage:

```python
from dcrx import Image

hello_world = Image("hello-world", tag="latest")

hello_world.stage(
    "python",
    "3.11-slim",
    alias="build"
)
```

which translates to:

```
FROM python:3.11-slim as build
```

This is particularly useful for multi-stage builds.

Next let's chain a call to the `entrypoint()` method, passing a list consisting of the CLI command (`echo` in this instance) and positional or keyword arguments/values we want to use:

```python
from dcrx import Image

hello_world = Image("hello-world", tag="latest")

hello_world.stage(
    "python",
    "3.11-slim"
).entrypoint([
    "echo",
    "Hello world!"
])
```

the call to `entrypoint()` translates directly to:

```
ENTRYPOINT ["echo", "Hello world!"]
```

just like you would write in a Dockerfile.

Finally, we need to write our dcrx image to an actual Dockerfile! Let's chain a final call to `to_file()` passing `Dockerfile` as the sole argument.

```python
from dcrx import Image

hello_world = Image("hello-world", tag="latest")

hello_world.stage(
    "python",
    "3.11-slim"
).entrypoint([
    "echo",
    "Hello world!"
]).to_file("Dockerfile")
```

Now run the script:

```bash
python hello_world.py
```

You'll immediately see our `Dockerfile` is generated in-directory. Opening it up, we see:

```docker
FROM python:3.11-slim

ENTRYPOINT ["echo", "Hello world!"]
```

Now build your image as you normally would:

```bash
docker build -t hello-world:latest .
```

and run it:

```bash
docker run hello-world:latest
```

which outputs:

```bash
Hello world!
```

to console. The image works exactly like we'd expect it to! Congrats on building your first dcrx image!

<br/>

# Parsing and Resolving Images

As of version `0.3.0`, dcrx now facilitates image loading and resolution allowing you to ingest, simplify, and search Dockerfiles.

Let's start by creating the following `Dockerfile` in an empty directory of your choice:

```docker
# Dockerfile
ARG PYTHON_VERSION
ARG PYTHON_FILE=test.py
FROM python:${PYTHON_VERSION}

RUN apt-get update -y && apt-get install -y python3-dev
RUN mkdir /src

COPY ${PYTHON_FILE} /src

EXPOSE 8000

CMD ["python", ${PYTHON_FILE}]
```

This image tags two arguments, one for the Python version (with no default), and one specifying a Python script to copy and run.

We want generate a series of images for Python versions 3.10, 3.11, and 3.12. To do so, let's create a Python script `generate_python_images.py`. As before, we'll start by importing the `Image` class:

```python
# generate_python_images.py
from dcrx import Image
```

The image class has several methods to load images from files:

- `from_file()` - Loads the specified Dockerfile into the current `Image` instance.

- `from_string()` - Parses a Dockerfile already read as existing string, list of strings, bytes, or list of bytes into the current `Image` instance.

- `generate_from_file()` - Loads the specified Dockerfile and generates a new `Image` file instance. This is a `classmethod` and does not require an existing `Image` instance.

- `generate_from_string()` - Parses a Dockerfile already read as existing string, list of strings, bytes, or list of bytes and generates a new `Image` file instance. This is a `classmethod` and does not require an existing `Image` instance.

When choosing between `generate` or `from` methods, consider whether you want to generate a <i>new</i> `Image` or simply want to load a Dockerfile into and existing `Image`. In this case, since we want to generate a series of new image files, we'll use the `generate_from_file` method. Add the following to you Python script:

```python
# generate_python_images.py
from dcrx import Image


image_versions = [
    '3.10-slim',
    '3.11-slim',
    '3.12-slim'
]

for version in image_versions:
    version_stub = version.replace('.', '')
    version_tag = f'python-{version_stub}'

    image = Image.generate_from_file(
        'Dockerfile.python-template',
        output_path=f'Dockerfile.{version_tag}'
    )
    
    image.name = 'python'
    image.tag = version_tag

    print(image.path)
```

Go ahead and run the script:

```bash
python generate_python_images.py
```

which should output:

```bash
Dockerfile.python-310-slim
Dockerfile.python-311-slim
Dockerfile.python-312-slim
```

Awesome! We're able to generate the three distinct image instances. Let's explore our images a bit more. Let's examine our generated images' `FROM` directes via the `layers()` method. Modify your script as below:

```python
# generate_python_images.py
from dcrx import Image


image_versions = [
    '3.10-slim',
    '3.11-slim',
    '3.12-slim'
]

for version in image_versions:
    version_stub = version.replace('.', '')
    version_tag = f'python-{version_stub}'

    image = Image.generate_from_file(
        'Dockerfile.python-template',
        output_path=f'Dockerfile.{version_tag}'
    )
    
    image.name = 'python'
    image.tag = version_tag
    
    print(image.path)

    stage_layers = image.layers(layer_types='stage')
    for stage in stage_layers:
        print(stage.base, stage.tag, '\n')
```

run the script again, which should output:

```bash
Dockerfile.python-310-slim
python ${PYTHON_VERSION}

Dockerfile.python-311-slim
python ${PYTHON_VERSION}

Dockerfile.python-312-slim
python ${PYTHON_VERSION}
```

while our script ran successfully, the images aren't build ready, still containing the templated arguments. This is where the `resolve()` method comes in! The `resolve()` method flood-fills an Image based upon any defaults supplied to `ARG` or `ENV` directes (or an optional dictionary specifying `ARG`/`ENV` names or keys and value defaults).

Let's modify our script once again as below:

```python
# generate_python_images.py
from dcrx import Image


image_versions = [
    '3.10-slim',
    '3.11-slim',
    '3.12-slim'
]

for version in image_versions:
    version_stub = version.replace('.', '')
    version_tag = f'python-{version_stub}'

    image = Image.generate_from_file(
        'Dockerfile.python-template',
        output_path=f'Dockerfile.{version_tag}'
    )
    
    image.name = 'python'
    image.tag = version_tag
    
    # Resolve our Image here:
    image = image.resolve(
        defaults={
            # Note that since PYTHON_VERSION doesn't have
            # a default, we should use the "defaults" optionsl
            # arg to provide one from our array of versions.
            'PYTHON_VERSION': version
        }
    )

    stage_layers = image.layers(layer_types='stage')
    for stage in stage_layers:
        print(stage.base, stage.tag, '\n')
```

Run the script again, which should output:

```
python 3.10-slim

python 3.11-slim

python 3.12-slim
```

Let's modify the script once more, adding  a call to `to_file()` to output our images to file: 

```python
# generate_python_images.py
from dcrx import Image


image_versions = [
    '3.10-slim',
    '3.11-slim',
    '3.12-slim'
]

for version in image_versions:
    version_stub = version.replace('.', '')
    version_tag = f'python-{version_stub}'

    image = Image.generate_from_file(
        'Dockerfile.python-template',
        output_path=f'Dockerfile.{version_tag}'
    )
    
    image.name = 'python'
    image.tag = version_tag
    
    # Resolve our Image here:
    image = image.resolve(
        defaults={
            'PYTHON_VERSION': version
        }
    )

    image.to_file()
```

and run the script again:

```bash
python generate_python_images.py
```

Note that the script now generates three distinct Dockerfiles - `Dockerfile.python-310-slim`, `Dockerfile.python-311-slim`, and `Dockerfile.python-312-slim`. Let's examine, `Dockerfile.python-312-slim`:

```docker
ARG PYTHON_VERSION="3.12-slim"

ARG PYTHON_FILE="test.py"

FROM python:3.12-slim

RUN apt-get update -y && apt-get install -y python3-dev

RUN mkdir /src

COPY ./test.py /src

EXPOSE 8000

CMD ["python", "test.py"]
```

Not just `PYTHON_VERSION`, but any directive referencing `PYTHON_FILE` has been fully resolved to its default. While we want to resolve the `PYTHON_VERSION`, we may still want to specify `PYTHON_FILE` at build time. Let's modify the script once more, using the `skip` optional arg to ensure the `PYTHON_FILE` arg is not resolved:

```python
# generate_python_images.py
from dcrx import Image


image_versions = [
    '3.10-slim',
    '3.11-slim',
    '3.12-slim'
]

for version in image_versions:
    version_stub = version.replace('.', '')
    version_tag = f'python-{version_stub}'

    image = Image.generate_from_file(
        'Dockerfile.python-template',
        output_path=f'Dockerfile.{version_tag}'
    )
    
    image.name = 'python'
    image.tag = version_tag
    
    # Resolve our Image here:
    image = image.resolve(
        defaults={
            'PYTHON_VERSION': version
        },
        skip=['PYTHON_FILE']
    )

    image.to_file()
```

and then run the script one final time:

```bash
python generate_python_image.py
```

Examining `Dockerfile.python-312-slim` once more:

```docker
ARG PYTHON_VERSION="3.12-slim"

ARG PYTHON_FILE="test.py"

FROM python:3.12-slim

RUN apt-get update -y && apt-get install -y python3-dev

RUN mkdir /src

COPY ./${PYTHON_FILE} /src

EXPOSE 8000

CMD ["python", "${PYTHON_FILE}"]
```

Perfect! We've now generated the Dockerfiles required!

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/scorbettUM/dcrx",
    "name": "dcrx",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": "",
    "keywords": "pypi,cicd,python,setup,docker,infra,devops",
    "author": "Sean Corbett",
    "author_email": "sean.corbett@umontana.edu",
    "download_url": "https://files.pythonhosted.org/packages/b9/11/9fe1aa80ab4223efdd905f7c4240502d414af8f9d7aa455c178c6f00b20c/dcrx-0.3.4.tar.gz",
    "platform": null,
    "description": "# dcrx\n[![PyPI version](https://img.shields.io/pypi/v/dcrx?color=gre)](https://pypi.org/project/dcrx/)\n[![License](https://img.shields.io/github/license/scorbettUM/dcrx)](https://github.com/scorbettUM/dcrx/blob/main/LICENSE)\n[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](https://github.com/scorbettUM/dcrx/blob/main/CODE_OF_CONDUCT.md)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/dcrx)](https://pypi.org/project/dcrx/)\n\n\nDockerX (dcrx) is a library for creating Docker images via an SQL query-builder like API. It is designed to facilitate programmatic, typesafe, and in-memory image generation. dcrx is *not* a wrapper around the Docker CLI or API, nor is it an implementation of these things. Rather, it is designed a lightweight, single-dependency means of writing and creating images that can then be provided to the Docker CLI or SDK for consumption.\n\n\n# Setup and Install\n\ndcrx is available via PyPi as an installable package. We recommend using Python 3.10+ and a virtual environment. To install dcrx, run:\n\n```bash\npython -m venv ~/.dcrx && \\\nsource ~/.dcrx/bin/activate && \\\npip install dcrx\n```\n\n\n# Getting Started\n\ndcrx uses a combination of method chaining common to SQL query builder libraries with Pydantic type validation to help you build images with fewer mistakes. As an example, let's create a basic Docker image that echoes \"Hello world!\" to output upon running the Docker image.\n\nFirst let's create an empty Python file:\n\n```\ntouch hello_world.py\n```\n\nOpen the file and import `Image` from `dcrx`:\n\n```python\nfrom dcrx import Image\n```\n\nThe Image class is the primary and only interface for generating and working with Docker images in dcrx. Let's go ahead and create an instance:\n\n```python\nfrom dcrx import Image\n\n\nhello_world = Image(\"hello-world\")\n```\n\nNote that we need to provide the name of the image to our class. We can also provide a tag via the `tag` keyword argument if needed (the default is `latest`):\n\n```python\nfrom dcrx import Image\n\nhello_world = Image(\"hello-world\", tag=\"latest\")\n```\n\nNext let's call the `stage()` method on our `hello_world` Image instance, passing both the base image name and image tag from which we want to create our image. We'll use `python` as our base image and `3.11-slim` as our tag:\n\n```python\nfrom dcrx import Image\n\nhello_world = Image(\"hello-world\", tag=\"latest\")\n\nhello_world.stage(\n    \"python\",\n    \"3.11-slim\"\n)\n```\n\nThis call translates directly to:\n\n```\nFROM python:3.11-slim\n```\n\nunderneath, just as if you were writing it in the image yourself! You can also use the optional `alias` arg to name the stage:\n\n```python\nfrom dcrx import Image\n\nhello_world = Image(\"hello-world\", tag=\"latest\")\n\nhello_world.stage(\n    \"python\",\n    \"3.11-slim\",\n    alias=\"build\"\n)\n```\n\nwhich translates to:\n\n```\nFROM python:3.11-slim as build\n```\n\nThis is particularly useful for multi-stage builds.\n\nNext let's chain a call to the `entrypoint()` method, passing a list consisting of the CLI command (`echo` in this instance) and positional or keyword arguments/values we want to use:\n\n```python\nfrom dcrx import Image\n\nhello_world = Image(\"hello-world\", tag=\"latest\")\n\nhello_world.stage(\n    \"python\",\n    \"3.11-slim\"\n).entrypoint([\n    \"echo\",\n    \"Hello world!\"\n])\n```\n\nthe call to `entrypoint()` translates directly to:\n\n```\nENTRYPOINT [\"echo\", \"Hello world!\"]\n```\n\njust like you would write in a Dockerfile.\n\nFinally, we need to write our dcrx image to an actual Dockerfile! Let's chain a final call to `to_file()` passing `Dockerfile` as the sole argument.\n\n```python\nfrom dcrx import Image\n\nhello_world = Image(\"hello-world\", tag=\"latest\")\n\nhello_world.stage(\n    \"python\",\n    \"3.11-slim\"\n).entrypoint([\n    \"echo\",\n    \"Hello world!\"\n]).to_file(\"Dockerfile\")\n```\n\nNow run the script:\n\n```bash\npython hello_world.py\n```\n\nYou'll immediately see our `Dockerfile` is generated in-directory. Opening it up, we see:\n\n```docker\nFROM python:3.11-slim\n\nENTRYPOINT [\"echo\", \"Hello world!\"]\n```\n\nNow build your image as you normally would:\n\n```bash\ndocker build -t hello-world:latest .\n```\n\nand run it:\n\n```bash\ndocker run hello-world:latest\n```\n\nwhich outputs:\n\n```bash\nHello world!\n```\n\nto console. The image works exactly like we'd expect it to! Congrats on building your first dcrx image!\n\n<br/>\n\n# Parsing and Resolving Images\n\nAs of version `0.3.0`, dcrx now facilitates image loading and resolution allowing you to ingest, simplify, and search Dockerfiles.\n\nLet's start by creating the following `Dockerfile` in an empty directory of your choice:\n\n```docker\n# Dockerfile\nARG PYTHON_VERSION\nARG PYTHON_FILE=test.py\nFROM python:${PYTHON_VERSION}\n\nRUN apt-get update -y && apt-get install -y python3-dev\nRUN mkdir /src\n\nCOPY ${PYTHON_FILE} /src\n\nEXPOSE 8000\n\nCMD [\"python\", ${PYTHON_FILE}]\n```\n\nThis image tags two arguments, one for the Python version (with no default), and one specifying a Python script to copy and run.\n\nWe want generate a series of images for Python versions 3.10, 3.11, and 3.12. To do so, let's create a Python script `generate_python_images.py`. As before, we'll start by importing the `Image` class:\n\n```python\n# generate_python_images.py\nfrom dcrx import Image\n```\n\nThe image class has several methods to load images from files:\n\n- `from_file()` - Loads the specified Dockerfile into the current `Image` instance.\n\n- `from_string()` - Parses a Dockerfile already read as existing string, list of strings, bytes, or list of bytes into the current `Image` instance.\n\n- `generate_from_file()` - Loads the specified Dockerfile and generates a new `Image` file instance. This is a `classmethod` and does not require an existing `Image` instance.\n\n- `generate_from_string()` - Parses a Dockerfile already read as existing string, list of strings, bytes, or list of bytes and generates a new `Image` file instance. This is a `classmethod` and does not require an existing `Image` instance.\n\nWhen choosing between `generate` or `from` methods, consider whether you want to generate a <i>new</i> `Image` or simply want to load a Dockerfile into and existing `Image`. In this case, since we want to generate a series of new image files, we'll use the `generate_from_file` method. Add the following to you Python script:\n\n```python\n# generate_python_images.py\nfrom dcrx import Image\n\n\nimage_versions = [\n    '3.10-slim',\n    '3.11-slim',\n    '3.12-slim'\n]\n\nfor version in image_versions:\n    version_stub = version.replace('.', '')\n    version_tag = f'python-{version_stub}'\n\n    image = Image.generate_from_file(\n        'Dockerfile.python-template',\n        output_path=f'Dockerfile.{version_tag}'\n    )\n    \n    image.name = 'python'\n    image.tag = version_tag\n\n    print(image.path)\n```\n\nGo ahead and run the script:\n\n```bash\npython generate_python_images.py\n```\n\nwhich should output:\n\n```bash\nDockerfile.python-310-slim\nDockerfile.python-311-slim\nDockerfile.python-312-slim\n```\n\nAwesome! We're able to generate the three distinct image instances. Let's explore our images a bit more. Let's examine our generated images' `FROM` directes via the `layers()` method. Modify your script as below:\n\n```python\n# generate_python_images.py\nfrom dcrx import Image\n\n\nimage_versions = [\n    '3.10-slim',\n    '3.11-slim',\n    '3.12-slim'\n]\n\nfor version in image_versions:\n    version_stub = version.replace('.', '')\n    version_tag = f'python-{version_stub}'\n\n    image = Image.generate_from_file(\n        'Dockerfile.python-template',\n        output_path=f'Dockerfile.{version_tag}'\n    )\n    \n    image.name = 'python'\n    image.tag = version_tag\n    \n    print(image.path)\n\n    stage_layers = image.layers(layer_types='stage')\n    for stage in stage_layers:\n        print(stage.base, stage.tag, '\\n')\n```\n\nrun the script again, which should output:\n\n```bash\nDockerfile.python-310-slim\npython ${PYTHON_VERSION}\n\nDockerfile.python-311-slim\npython ${PYTHON_VERSION}\n\nDockerfile.python-312-slim\npython ${PYTHON_VERSION}\n```\n\nwhile our script ran successfully, the images aren't build ready, still containing the templated arguments. This is where the `resolve()` method comes in! The `resolve()` method flood-fills an Image based upon any defaults supplied to `ARG` or `ENV` directes (or an optional dictionary specifying `ARG`/`ENV` names or keys and value defaults).\n\nLet's modify our script once again as below:\n\n```python\n# generate_python_images.py\nfrom dcrx import Image\n\n\nimage_versions = [\n    '3.10-slim',\n    '3.11-slim',\n    '3.12-slim'\n]\n\nfor version in image_versions:\n    version_stub = version.replace('.', '')\n    version_tag = f'python-{version_stub}'\n\n    image = Image.generate_from_file(\n        'Dockerfile.python-template',\n        output_path=f'Dockerfile.{version_tag}'\n    )\n    \n    image.name = 'python'\n    image.tag = version_tag\n    \n    # Resolve our Image here:\n    image = image.resolve(\n        defaults={\n            # Note that since PYTHON_VERSION doesn't have\n            # a default, we should use the \"defaults\" optionsl\n            # arg to provide one from our array of versions.\n            'PYTHON_VERSION': version\n        }\n    )\n\n    stage_layers = image.layers(layer_types='stage')\n    for stage in stage_layers:\n        print(stage.base, stage.tag, '\\n')\n```\n\nRun the script again, which should output:\n\n```\npython 3.10-slim\n\npython 3.11-slim\n\npython 3.12-slim\n```\n\nLet's modify the script once more, adding  a call to `to_file()` to output our images to file: \n\n```python\n# generate_python_images.py\nfrom dcrx import Image\n\n\nimage_versions = [\n    '3.10-slim',\n    '3.11-slim',\n    '3.12-slim'\n]\n\nfor version in image_versions:\n    version_stub = version.replace('.', '')\n    version_tag = f'python-{version_stub}'\n\n    image = Image.generate_from_file(\n        'Dockerfile.python-template',\n        output_path=f'Dockerfile.{version_tag}'\n    )\n    \n    image.name = 'python'\n    image.tag = version_tag\n    \n    # Resolve our Image here:\n    image = image.resolve(\n        defaults={\n            'PYTHON_VERSION': version\n        }\n    )\n\n    image.to_file()\n```\n\nand run the script again:\n\n```bash\npython generate_python_images.py\n```\n\nNote that the script now generates three distinct Dockerfiles - `Dockerfile.python-310-slim`, `Dockerfile.python-311-slim`, and `Dockerfile.python-312-slim`. Let's examine, `Dockerfile.python-312-slim`:\n\n```docker\nARG PYTHON_VERSION=\"3.12-slim\"\n\nARG PYTHON_FILE=\"test.py\"\n\nFROM python:3.12-slim\n\nRUN apt-get update -y && apt-get install -y python3-dev\n\nRUN mkdir /src\n\nCOPY ./test.py /src\n\nEXPOSE 8000\n\nCMD [\"python\", \"test.py\"]\n```\n\nNot just `PYTHON_VERSION`, but any directive referencing `PYTHON_FILE` has been fully resolved to its default. While we want to resolve the `PYTHON_VERSION`, we may still want to specify `PYTHON_FILE` at build time. Let's modify the script once more, using the `skip` optional arg to ensure the `PYTHON_FILE` arg is not resolved:\n\n```python\n# generate_python_images.py\nfrom dcrx import Image\n\n\nimage_versions = [\n    '3.10-slim',\n    '3.11-slim',\n    '3.12-slim'\n]\n\nfor version in image_versions:\n    version_stub = version.replace('.', '')\n    version_tag = f'python-{version_stub}'\n\n    image = Image.generate_from_file(\n        'Dockerfile.python-template',\n        output_path=f'Dockerfile.{version_tag}'\n    )\n    \n    image.name = 'python'\n    image.tag = version_tag\n    \n    # Resolve our Image here:\n    image = image.resolve(\n        defaults={\n            'PYTHON_VERSION': version\n        },\n        skip=['PYTHON_FILE']\n    )\n\n    image.to_file()\n```\n\nand then run the script one final time:\n\n```bash\npython generate_python_image.py\n```\n\nExamining `Dockerfile.python-312-slim` once more:\n\n```docker\nARG PYTHON_VERSION=\"3.12-slim\"\n\nARG PYTHON_FILE=\"test.py\"\n\nFROM python:3.12-slim\n\nRUN apt-get update -y && apt-get install -y python3-dev\n\nRUN mkdir /src\n\nCOPY ./${PYTHON_FILE} /src\n\nEXPOSE 8000\n\nCMD [\"python\", \"${PYTHON_FILE}\"]\n```\n\nPerfect! We've now generated the Dockerfiles required!\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "A library for typesafe, programmatic generation of Docker images via SQL-builder like API.",
    "version": "0.3.4",
    "project_urls": {
        "Homepage": "https://github.com/scorbettUM/dcrx"
    },
    "split_keywords": [
        "pypi",
        "cicd",
        "python",
        "setup",
        "docker",
        "infra",
        "devops"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "679db773b43083839fc1320a4716e136c03d998c0bedd5356c356239e4803c06",
                "md5": "c43b95eaa7300ab676ed60f6dae9a8e2",
                "sha256": "f772af82df7a0ee9daab87d06208e03bc905ddcbbeebf298a47070123a719f1c"
            },
            "downloads": -1,
            "filename": "dcrx-0.3.4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "c43b95eaa7300ab676ed60f6dae9a8e2",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 31445,
            "upload_time": "2024-01-18T21:34:26",
            "upload_time_iso_8601": "2024-01-18T21:34:26.190575Z",
            "url": "https://files.pythonhosted.org/packages/67/9d/b773b43083839fc1320a4716e136c03d998c0bedd5356c356239e4803c06/dcrx-0.3.4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b9119fe1aa80ab4223efdd905f7c4240502d414af8f9d7aa455c178c6f00b20c",
                "md5": "a8136b516e031e5598f2b5dc2dc9ce6c",
                "sha256": "1ac80d198bbf8af49582563fc4600f1ba17b07b9556bfaa1ad4f97f17f5ddfa0"
            },
            "downloads": -1,
            "filename": "dcrx-0.3.4.tar.gz",
            "has_sig": false,
            "md5_digest": "a8136b516e031e5598f2b5dc2dc9ce6c",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 23368,
            "upload_time": "2024-01-18T21:34:27",
            "upload_time_iso_8601": "2024-01-18T21:34:27.860803Z",
            "url": "https://files.pythonhosted.org/packages/b9/11/9fe1aa80ab4223efdd905f7c4240502d414af8f9d7aa455c178c6f00b20c/dcrx-0.3.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-01-18 21:34:27",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "scorbettUM",
    "github_project": "dcrx",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "pydantic",
            "specs": []
        }
    ],
    "lcname": "dcrx"
}
        
Elapsed time: 0.29457s