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

[gen] Implement gen prod dockerfile #2017

Merged
merged 4 commits into from
Apr 24, 2024
Merged

Conversation

mikeland73
Copy link
Contributor

Summary

Simple implementation for generating a prod dockerfile from a devbox project.

Notes:

  • Flag to create this is hidden.
  • Currently this requires a start script. There are also optional install and build scripts.

Follow ups:

  • In addition to start script I want to support services but I was having trouble getting process compose to start as Dockerfile CMD. Will debug further and add in follow up.
  • We can greatly optimize the Dockerfile by downloading devbox dependencies first before coping source code. This will likely require a new devbox command or flag.

How was it tested?

Tested using this project https://github.com/mikeland73/hello-world-server

devbox generate dockerfile --for prod
docker build . -t hello-world
docker run -p 8080:8080 hello-world


COPY --chown=${DEVBOX_USER}:${DEVBOX_USER} . .

RUN devbox install
Copy link
Collaborator

Choose a reason for hiding this comment

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

There was an issue with using devbox install command in dockerfile. IIRC it didn't activate the python plugin so the subsequent python commands were not running in a virtual environment.

Copy link
Collaborator

Choose a reason for hiding this comment

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

this is the issue I'm talking about:
#1122

can you test the steps in the issue to make sure we don't regress?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm a bit confused by that issue. I understand that install doesn't run init hooks, but I would assume the line below

RUN devbox shellenv --init-hook >> ~/.profile

Would do the initialization.

Furthermore, actually activating the virtual environment is a manual process so neither install/run would do it.

Do you know why shellenv is not working?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

FWIW, since the prod dockerfile always ends in devbox run start it will always run the init hook which creates the virtenv. To activate it, the user would need to add that to their start command. Maybe we can add an env variable that automatically activates it.


RUN {{ .DevboxRunBuild }}

CMD [{{ .Cmd }}]
Copy link
Collaborator

@LucilleH LucilleH Apr 24, 2024

Choose a reason for hiding this comment

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

I hope we can optimize this image further, especially it is supposedly for prod. Right now it builds for a long time and the image ends up super big. Something like:

  • gc nix store (clean up)
  • devbox shellenv (so cmd has the right env)
  • separate install layer

Although I don't know how much those steps could help.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@LucilleH for sure! I think some of those might be doable without devbox changes (but not all).

gc nix store (clean up)

I can try this, but in theory the nix store should be pretty clean no? We haven't installed anything we don't need.

devbox shellenv

This can help a bit but not without changes. Ideally, we do shellenv and then call the raw start command (without using devbox run). A small concern is the init hook not running multiple times (I think that's probably fine). So in practice it would look like:

RUN eval $(devbox shellenv --init-hook)
RUN devbox run install --raw
RUN devbox run build --raw
CMD ["devbox", "run", "start", "--raw"] 

Where --raw would be a new flag that indicates run the raw script without starting a devbox env (which would be wasteful)

separate install layer

This is the biggest win. But see my comment about local dependencies. I think there's 2 huge optimizations here:

  • Do devbox install before copying source code. This makes a very cachable base layer.
  • Split stages so that we copy over only nix stuff we need into final image.

(1) is easy, but requires a new flag/command so we can ignore errors of missing local dependencies.
(2) is harder, but we did something similar in early devbox days.

My preference is to merge this and optimize in follow up. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Apparently RUN eval $(devbox shellenv --init-hook) is not a thing you can do because each RUN runs in own shell. So maybe something like

RUN devbox shellenv --init-hook >> ~/.profile

@mikeland73
Copy link
Contributor Author

Gonna merge this and improve in follow up.

@mikeland73 mikeland73 merged commit a55a74b into main Apr 24, 2024
24 checks passed
@mikeland73 mikeland73 deleted the landau/generate-prod-dockerfile branch April 24, 2024 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants