commercialhaskell / commercialhaskell/stack
Improve docker image building support
- Dominant language
- Haskell
- Stars
- 4.1k
- Forks
- 850
- Avg merge
- 10h 37m
- Merged PRs (30d)
- 4
Description
I'm planning to improve the docker image support for Stack.
Currently, stack supports some features for building slim containers containing the executables with the `stack image container`
1. generate a base docker image of your (umbrella) project.
This means, multiple targets (cabal files) are built and put in the same image.
With the `executables` option you can target which executables end up in the image. So
if you have a stack project like:
```
❯ tree
umbrella
├── bar
│ ├── A.hs
│ ├── bar.cabal
│ ├── B.hs
│ └── package.yaml
├── baz
│ ├── A.hs
│ ├── baz.cabal
│ ├── B.hs
│ └── package.yaml
├── foo
│ ├── A.hs
│ ├── B.hs
│ ├── foo.cabal
│ └── package.yaml
└── stack.yaml
```
One docker image named `umbrella:latest` will be generated.
2. Create derivate images with `ENTRYPOINT` set to the executables that there is a docker image
for each executable. So for the above example we could generate the following docker images:
```
umbrella-foo-a:latest
umbrella-foo-b:latest
umbrella-bar-a:latest
umbrella-bar-b:latest
umbrella-baz-a:latest
umbrella-baz-b:latest
```
3. All images are always tagged with the `latest` tag, instead of the library versions. This is understandable,
because an umbrella project consists of multiple libraries, and then the question is, which version to use to tag the docker image?
However, these features are a little bit fragile. For exampe, the `entrypoints` option does not check if the executable actually exists.
I would like to improve the image building support a bit, by making it a bit more `stack aware`. Currently, the approach is totally file based, and doesn't know about what targets there are, and what executables exist.
Features I want to implement:
1. Have a base image per build target instead of one base image for the entire stack project
So if you have an umbrella project with multiple cabal projects there will be a base image for each cabal project created. Because we now have a base image per target. We can tag the base image with the target package version. this is nice because now you can keep track of what version of images you are running in production
So for the above mentioned `umbrella` project, the following base images will be generated:
```
foo:0.1.0
bar:0.2.0
baz:0.1.1
```
3. To get the entrypoint images, instead of iterating over the `entrypoints` field in `stack.yaml`, we could
now just look at the `target` metadata in `stack` and generate a docker image with the correct `ENTRYPOINT` for each `executable` section in the cabal file, along with the correct version tag
```
foo-foo-a:0.1.0
foo-foo-b:0.1.0
bar-bar-a:0.2.0
bar-bar-b:0.2.0
baz-baz-a:0.1.1
baz-baz-b:0.1.1
```
Now the questions to you:
1. Do you agree with this design and would like to have this added? I think it will make
deploying haskell in `kubernetes` etc even easier. Please leave any feedback in the comments. Perhaps
we should discuss this a bit before I start implementing new features.
2. I'm not familiar with the code base too much, so can I ask questions for pointers where to get certain information that I need to get this done?
3. What about backwards compatibility? I have not really thought of it.
Contributor guide
Assessment
This issue has not been assessed yet.