Docker implementation#1219
Conversation
9fa7db8 to
9f20cbe
Compare
| """ | ||
| Base image to use for docker builds when `installer_type` includes `docker` or `docker_build` is True. | ||
| Should be a specific image reference. For reproducibility, please specify a SHA256 digest. | ||
| For example: `debian:13.4-slim@sha256:abc123...`. If the digest is not provided, a warning will be shown. |
There was a problem hiding this comment.
The example is great, but reproducibility is not the primary concern here either, it's supply chain security. I would overall do don't think it's constructor's responsibility to decide or advise on the user's security model though, even if it's just a warning. Warnings show up in GitHub Action summaries and can introduce unwanted noise.
There was a problem hiding this comment.
So, remove the SHA256 warning altogether? Or just rephrase it to be neutral?
Base image to use for docker builds when `installer_type` includes `docker` or `docker_build` is True.
Should be a specific image reference. For example: `debian:13.4-slim@sha256:abc123...`.
There was a problem hiding this comment.
I would remove this altogether, so remove "Should be...", but definitely keep the example as is.
| """ | ||
| If `True`, builds a docker image using the Dockerfile generated by constructor and saves it as a portable tarball. | ||
| ``<name>-<version>-<platform>.tar`` will be created in the output docker directory. | ||
| Requires `docker_base_image` to be specified. |
There was a problem hiding this comment.
The base image should be a mandatory parameter in any case.
There was a problem hiding this comment.
I'm not sure I'm following here as the base image being required is already enforced. Is saying Requires `docker_base_image` to be specified. misleading?
There was a problem hiding this comment.
I would call it redundant since all Docker parameters require the base image to be set.
There was a problem hiding this comment.
Ahh, it is true it's required, but I think it's helpful for those who don't know the code and just look at the schema.
There was a problem hiding this comment.
I think the right place to declare that is with docker_base_image, not docker_build (or why in docker_build and not the other docker options?). You could write in docker_base_image that this is a required parameter to make it very explicit.
| The labels `org.opencontainers.image.title` and `org.opencontainers.image.version` are | ||
| set automatically from `name` and `version`. | ||
| """ | ||
| docker_build: bool = False |
There was a problem hiding this comment.
Given that Docker provides several output formats, I would rather choose something that is extendable. It's okay if we don't support all formats right now, we can disclose that.
There was a problem hiding this comment.
Can you please clarify what you have in mind here? Are you suggesting we do something like docker_output: tarball in place of docker_build: True?
There was a problem hiding this comment.
Correct, that's what I suggest. The available options should correspond verbatim to the same option Docker supports (uncompressed, etc.).
| message: "This base environment is frozen and cannot be modified." | ||
| ``` | ||
| """ | ||
| docker_base_image: Annotated[str, Field(min_length=1)] | None = None |
There was a problem hiding this comment.
Instead of prefixing all fields with docker_*, would it make more sense to make docker its own key with all other properties being a subkey? I know that's not our current convention, so I'm not 100% sure about that.
There was a problem hiding this comment.
I agree it could be cleaner, but unless we can do a broader refactor, I think docker_* keeps things consistent with how it's handled today.
There was a problem hiding this comment.
Also, please volunteer me if/when we can do a schema refactor. (:
There was a problem hiding this comment.
Sticking with the current schema is a fair choice. A schema refactor would constitute a major breaking change that I don't foresee ourselves doing unless we absolutely have to.
| docker_tag: NonEmptyStr | None = None | ||
| """ | ||
| Tag to use for the docker image. | ||
| If not provided, it will default to `<name>:<version>`. |
There was a problem hiding this comment.
Do we need to provide a default here? docker build runs with a tag, too.
Will this require docker_build (or whatever successor you choose) to be set?
There was a problem hiding this comment.
I don't think we should. It's handled in the script, but I could add something like Has no effect if `docker_build` or `docker_output` is not set.
There was a problem hiding this comment.
I actually wrote the opposite of what I meant to write: docker build runs without a tag, too. So, tagging the image isn't necessarily required for it to work. Definitely disclose in the schema when that option has no effect for the docker installer type.
There was a problem hiding this comment.
To clarify, it is highly suggested that a tag be used with docker build. The only thing is that it is not required for the user to come up with that tag because it will default to miniconda3:25.1.1 for example. Please let me know if that default is sufficient or if something like miniconda3-25.1.1:linux-arm64 would be better.
There was a problem hiding this comment.
Not sure if there's a limit on characters for the tag name, but the latter is definitely more descriptive. 😄
|
|
||
| LABEL org.opencontainers.image.title="{{ name }}" | ||
| LABEL org.opencontainers.image.version="{{ version }}" | ||
| {%- if labels %} |
There was a problem hiding this comment.
I don't think the if is needed. If labels is empty, the loop just won't run.
| if docker_build and osname == "win": | ||
| sys.exit( | ||
| "Error: 'docker_build' is not supported on Windows. " | ||
| "Run the build on Linux or macOS instead." | ||
| ) | ||
| if docker_build and itype in ("pkg", "exe"): | ||
| sys.exit( | ||
| "Error: 'docker_build' is not compatible with installer_type 'pkg' or 'exe'. " | ||
| "Use installer_type: 'sh', 'docker', or omit installer_type." | ||
| ) |
There was a problem hiding this comment.
Instead of erroring out, we should just ignore those.
| info["_outpath"] = abspath(join(output_dir, get_output_filename(info))).replace( | ||
| ".docker", ".sh" | ||
| ) |
There was a problem hiding this comment.
Aren't you already doing this in the build function?
There was a problem hiding this comment.
You're right. I'll remove it from docker_build.py and keep the path handling here so it's consistent with how the other installer types manage _outpath.
|
|
||
| @pytest.mark.skipif(sys.platform.startswith("win"), reason="Unix only") | ||
| @pytest.mark.skipif(not shutil.which("docker"), reason="Docker not available") | ||
| def test_docker_build(tmp_path): |
There was a problem hiding this comment.
This test doesn't test the labels.
| ), | ||
| "win": ("exe",), | ||
| } | ||
| all_allowed = set(sum(os_allowed.values(), ("all", "docker"))) |
There was a problem hiding this comment.
We only allow Docker for Linux platforms and can only build them on Linux and macOS.
There was a problem hiding this comment.
Does this mean I could do
os_allowed = {
"linux": ("sh", "docker"),
"osx": (
"sh",
"pkg",
),
"win": ("exe",),
}
and it would cover all the bases since constructor handles the cross-platform checks for us?
There was a problem hiding this comment.
I had this originally, but wasn't sure how to test the cross-platform check properly
There was a problem hiding this comment.
That would add docker to the all list for Linux, which may not be what you want. The platform here is actually the CLI argument, so cross-platform checks are done automatically. You may just need to write:
if itype == "docker" and osname == "linux":
return (itype,)
elif ...
|
@Jrice1317 I'd be happy to do a review once the items from Marco have been resolved, it'll also help me understand the changes better |
Co-authored-by: Marco Esters <mesters@anaconda.com>
…constructor into docker-implementation
Description
This PR adds Docker output support to constructor, generating a ready-to-use Dockerfile and optionally building the resulting image via
installer_type: dockeranddocker_build: truein the construct.yaml.Changes
New:
constructor/docker_build.py: Handles Docker output by rendering template and optionally building portable imageconstructor/dockerfile_template.tmpl: Template used to generate Dockerfileexamples/docker_build/construct.yaml: Example construct.yaml used for testingUpdated:
constructor/_schema.py: Addsdockertoinstaller_typeand addsdocker_base_image,docker_tag,docker_labelsconstructor/main.py: Addsdockerto installer typestests/test_examples.py: Addstest_docker_buildto cover Dockerfile generation, image build and smoke testNotes:
docker_buildisTrue, the user can start using the resulting portable image by running the commanddocker load -i <image_name>RuntimeErroris raised whenbase_imageis not providedChecklist - did you ...
newsdirectory (using the template) for the next release's release notes?