Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use a distroless base image #1656

Merged
merged 4 commits into from
Nov 22, 2021
Merged

Conversation

carolynvs
Copy link
Member

@carolynvs carolynvs commented Jul 2, 2021

What does this change

Use a distroless base image for our porter docker images. This has less of an attack surface because it only ships the essentials to run porter, not the extra stuff that usually comes with a linux distribution.

What issue does it fix

Part of getporter/operator#38

Notes for the reviewer

This relies on #1655 and needs to be rebased after that is merged.

Checklist

  • Unit Tests
  • Documentation
  • Schema (porter.yaml)

Use a distroless base image for our porter docker images. This
has less of an attack surface because it only ships
the essentials to run porter, not the extra stuff that usually comes
with a linux distribution.

Signed-off-by: Carolyn Van Slyck <me@carolynvanslyck.com>
Copy link
Contributor

@Church13 Church13 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestions to improve dockerfile and final image (without affecting functionality)

Signed-off-by: Carolyn Van Slyck <me@carolynvanslyck.com>

Co-authored-by: Nathaniel "Church" Hatfield <church13halo@gmail.com>
@carolynvs
Copy link
Member Author

@Church13 Previously the porter agent image had a script for an entry point. Will that still work?

FROM getporter/porter:latest

VOLUME /porter-config

COPY run.sh /

ENTRYPOINT ["/run.sh"]

When I try to run the image I am getting standard_init_linux.go:228: exec user process caused: no such file or directory which I assume is because of the shebang #!/usr/bin/env sh in my run.sh. Should I change this to a binary?

@Church13
Copy link
Contributor

Church13 commented Nov 18, 2021

@Church13 Previously the porter agent image had a script for an entry point. Will that still work?

FROM getporter/porter:latest

VOLUME /porter-config

COPY run.sh /

ENTRYPOINT ["/run.sh"]

When I try to run the image I am getting standard_init_linux.go:228: exec user process caused: no such file or directory which I assume is because of the shebang #!/usr/bin/env sh in my run.sh. Should I change this to a binary?

Distroless containers typically do not include shells. For google’s distroless image, “sh” is not an included binary. Can you show me the contents of run.sh? Ideally, it’s functionality would be replaced with a portable application, or with a more advanced entrypoint vector with all arguments and needed commands.

If the entrypoint specifies a binary, you can also precede it with multiple CMD vectors, like so:

CMD ["app:app", "--workers=2", "--threads=2", "-b 0.0.0.0:8080"]
ENTRYPOINT ["/usr/local/bin/gunicorn"]

@carolynvs
Copy link
Member Author

It's a very simple script that just copies some files where it needs to go before running. I'll make a binary and use that instead. I just wanted to confirm that was the right solution. Thanks!

@Church13
Copy link
Contributor

@carolynvs Moving a container to distroless is a big paradigm shift -- it's minimum level runtime, providing virtually no environment or operating system. Since you were using the distroless/static:debug image before, there was a busybox shell present for debugging, but this is not present in the nonroot production ready image.

From Google's GitHub distroless repo readme:

"Distroless" images contain only your application and its runtime dependencies. They do not contain package managers, shells or any other programs you would expect to find in a standard Linux distribution.

For more information, see this talk (video).

It's not unheard of to build a shell into a distroless image (read: distroless python, powershell), and there may be a good use case for doing so here -- but there are often different (and better) ways to build the image or utilize the application such that a shell isn't necessary.

Here's an interesting golang project I found on converting UNIX shell scripts to golang binaries (https://pkg.go.dev/github.com/ganbarodigital/go_scriptish) -- could be an avenue worth pursuing. As time allows I might look into converting the run.sh script to a static golang binary using this tool.

@Church13
Copy link
Contributor

It's a very simple script that just copies some files where it needs to go before running. I'll make a binary and use that instead. I just wanted to confirm that was the right solution. Thanks!

That works as well. Awesome!

Since the nonroot distroless image doesn't have a shell, we can't use
run.sh to copy the porter config files into PORTER_HOME at container
start. I have implemented that in Go (sorry it's a lot vs what good ole
cp did for us under the hood).

One trick is that when /porter-config is mounted into the container by
k8s, it uses symlinks like this:

/porter-config
  ..data/porter.config
  porter.config -> ..data/porter.config

So it's not a straightforward as you'd think at first glance.

Signed-off-by: Carolyn Van Slyck <me@carolynvanslyck.com>
@carolynvs
Copy link
Member Author

@Church13 I've replaced run.sh with a go binary (I have newfound respect for the humble cp), and updated the agent to not install mixins into the image (we needed to make that change regardless).

@carolynvs carolynvs marked this pull request as ready for review November 22, 2021 15:59
Copy link
Member

@vdice vdice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great to learn all about the distroless approach and best practices. LGTM.

Signed-off-by: Carolyn Van Slyck <me@carolynvanslyck.com>

Co-authored-by: Vaughn Dice <vaughn.dice@fermyon.com>
@carolynvs carolynvs merged commit 786738a into getporter:release/v1 Nov 22, 2021
@carolynvs carolynvs deleted the distroless branch November 22, 2021 21:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants