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

Add git, git-lfs, and openssh-client to the trame docker container #184

Closed
Besler opened this issue Jan 25, 2023 · 9 comments
Closed

Add git, git-lfs, and openssh-client to the trame docker container #184

Besler opened this issue Jan 25, 2023 · 9 comments

Comments

@Besler
Copy link

Besler commented Jan 25, 2023

Is your feature request related to a problem? Please describe.

I have many private python dependencies I specify through the remote git interface as such:

requirements.txt

django @ git+https://github.com/django/django@80d38de52bb2721a7b44fce4057bcff571afc23a

I currently cannot use them since the trame docker container does not contain git.
I get the following output from build_server.sh:

[...]
Processing /local-app
  Installing build dependencies: started
  Installing build dependencies: finished with status 'done'
  Getting requirements to build wheel: started
  Getting requirements to build wheel: finished with status 'done'
  Preparing metadata (pyproject.toml): started
  Preparing metadata (pyproject.toml): finished with status 'done'
Collecting *@ git+ssh://git@bitbucket.org/****/*.git@v0.2.0
  Cloning ssh://****@bitbucket.org/****/*.git (to revision v0.2.0) to /tmp/pip-install-86inj873/*_8ceacc16a7ac4ae9989ad1b36e837e76
  ERROR: Error [Errno 2] No such file or directory: 'git' while executing command git version
ERROR: Cannot find command 'git' - do you have 'git' installed and in your PATH?
Ignoring cffi: markers 'python_version >= "3.9" and python_version < "3.11" and sys_platform == "win32"' don't match your environment
Ignoring clr-loader: markers 'python_version >= "3.9" and python_version < "3.11" and sys_platform == "win32"' don't match your environment
Ignoring colorama: markers 'python_version >= "3.9" and python_version < "3.11" and platform_system == "Windows"' don't match your environment
Collecting ***@ git+ssh://git@bitbucket.org/****/***.git@v0.2.0
ERROR: Can't verify hashes for these requirements because we don't have a way to hash version control repositories:
    ***@ git+ssh://git@bitbucket.org/****/***.git@v0.2.0 from git+ssh://****@bitbucket.org/****/***.git@v0.2.0 (from -r /deploy/setup/requirements.txt (line 426))
/deploy/server/venv/bin/python: Error while finding module specification for 'trame.tools.www' (ModuleNotFoundError: No module named 'trame')
/deploy/server/venv/bin/python: Error while finding module specification for 'trame.tools.app' (ModuleNotFoundError: No module named 'trame')
/deploy/server/venv/bin/python: Error while finding module specification for 'trame.tools.app' (ModuleNotFoundError: No module named 'trame')
[...]

Describe the solution you'd like

Inclusion of git, git-lfs, and openssh-client in the docker container.

Inclusion of openssh-client and a poetry target would also be sufficient.

Describe alternatives you've considered

  1. poetry (instead of pip or conda) comes with dulwich as a python-only git client. This gets around git and git-lfs and can be installed in initialize.sh, but does not include ssh.

initialize.sh

# Install app from local directory
wget https://install.python-poetry.org -O - | POETRY_HOME=~/.poetry python && \
    export PATH="~/.poetry/bin:$PATH" && \
    poetry config virtualenvs.create false

pushd /local-app
poetry install
popd
  1. Maybe I could wget binaries of all these packages, drop them in a bin somewhere, and modify my path?

  2. Just write my own Dockerfile from scratch, bastardizing the nice setup.

Additional context

N/A

@psavery
Copy link
Collaborator

psavery commented Jan 25, 2023

@jourdain Maybe we should add a way for users to install needed root dependencies as part of the build? The current initialize.sh script that runs during the build is started with user-level privileges, so users wouldn't be able to do things like apt-get install git there.

@Besler For now, could you try to make a new docker image based off of the trame one that adds these? For instance:

FROM kitware/trame

RUN apt-get update && \
    apt-get install -y \
      git \
      git-lfs \
      openssh-client && \
    rm -rf /var/lib/apt/lists/*

Then you can run that docker image instead for building the server.

@jourdain
Copy link
Collaborator

Good point on having an initialize_as_root.sh option. But we need to keep in mind that the runtime after that won't have any of those packages (which could be fine). It also mean, that if someone needs packages for their runtime, they will simply need to create a new image base from ours (which seems totally fine for me).

I guess the real questions here are:

  • does it make sense to have openssh-client in our runtime? (same for git)
  • Since we heavily rely on Python, should we enable poetry as well (should it be a default on top of pip) or does it need its own image tree? (I don't know if Poetry and conda make sense together?)

@jourdain
Copy link
Collaborator

@Besler not sure if you can do anything about #18 or #19, but if will be greatly appreciate.

@Besler
Copy link
Author

Besler commented Jan 26, 2023

I really apologize for the delay, I will try my best to get back with feedback tonight.

@Besler
Copy link
Author

Besler commented Jan 27, 2023

@psavery

For now, could you try to make a new docker image based off of the trame one that adds these? For instance:

FROM kitware/trame

RUN apt-get update && \
    apt-get install -y \
      git \
      git-lfs \
      openssh-client && \
    rm -rf /var/lib/apt/lists/*

With just the above, I am unable to authorize the repositories, so I need to mount my ssh keys. I would typically build like such:
Command

DOCKER_BUILDKIT=1 docker build --ssh default -t demo .

Dockerfile

FROM ${BASE}

RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan bitbucket.org >> ~/.ssh/known_hosts
RUN --mount=type=ssh poetry install

I believe this is the recommended method for preventing your keys from leaking into the image layers. However, this doesn't work here since we're building through an ENTRYPOINT and not a RUN.

Now, I did try mounting my keys directly:
Dockerfile

FROM kitware/trame:glvnd

RUN apt-get update && \
    apt-get install -y \
      git \
      git-lfs \
      openssh-client && \
    rm -rf /var/lib/apt/lists/*

RUN  mkdir -p -m 0600 ~/.ssh && \
    chown -R trame-user:trame-user ~/.ssh && \
    echo "Host *\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config && \
    ssh-keyscan bitbucket.org >> ~/.ssh/known_hosts

Command

docker run --rm          \
    -v ~/.ssh:/home/user/.ssh:ro \
    -e TRAME_BUILD_ONLY=1 \
    -v "$DEPLOY_DIR:/deploy" \
    -v "$ROOT_DIR:/local-app"  \
    ondtrame build launcher venv www

But I get permission denied on the keys. I think this is a user error, and I would have to set my keys to trame-user, but I haven't figured that out yet.

Essentially, the kitware/trame process looks like it is duplicating the docker multi-stage build process. I am tempted to prefer the docker defined ssh methods with RUN --mount=default COMMAND since I trust it not to leak my keys and it is maintained by docker themselves. But, these modifications are some work. Any thoughts?

@jourdain

  • does it make sense to have openssh-client in our runtime? (same for git)

I would imagine not by default, since it is so easy to add to the final image through the Dockerfile. It's just needed for building server/

  • Since we heavily rely on Python, should we enable poetry as well (should it be a default on top of pip) or does it need its own image tree? (I don't know if Poetry and conda make sense together?)

One can also export to a requirements.txt. I'm not so sure it's worth the maintenance, but I'd like it! :p

@psavery
Copy link
Collaborator

psavery commented Jan 27, 2023

@Besler So, even though it isn't shown in the cookiecutter, you can also build your image through a RUN command. Instead of mounting the deploy directory, you would copy it. And then you would run the build command as a RUN command. Like this:

COPY --chown=trame-user:trame-user . /deploy
RUN /opt/trame/entrypoint.sh build

(Example here).

Maybe you can build with the ssh methods like that?

@Besler
Copy link
Author

Besler commented Jan 31, 2023

@psavery The issue I ran into is that the build.sh script is ran with gosu trame-user, causing the ssh credentials to fail since the user must be root to interface with ssh. My simple solution was to bypass gosu and do a multi-stage build, resulting in one file:

FROM kitware/trame:glvnd as builder

# Install git, git-lfs, and openssh-client
RUN apt-get update && \
    apt-get install -y \
      git \
      git-lfs \
      openssh-client && \
    rm -rf /var/lib/apt/lists/*

# Build
COPY --chown=trame-user:trame-user bundles/docker/ /deploy
COPY --chown=trame-user:trame-user . /local-app
RUN mkdir -p -m 0600 ~/.ssh && \
    ssh-keyscan bitbucket.org >> ~/.ssh/known_hosts
RUN --mount=type=ssh mkdir -p /deploy/server && /opt/trame/build.sh


FROM kitware/trame:glvnd as base

COPY --from=builder /deploy/server /deploy/server
#!/usr/bin/env bash
CURRENT_DIR=`dirname "$0"`

# Since Mac doesn't come with realpath by default, let's set the full
# paths using PWD.
pushd . > /dev/null
cd $CURRENT_DIR/..
DEPLOY_DIR=$PWD
cd $CURRENT_DIR/../../..
ROOT_DIR=$PWD
popd > /dev/null

DOCKER_BUILDKIT=1 docker build \
    --ssh default \
    -t myimage \
    $ROOT_DIR \
    -f $DEPLOY_DIR/Dockerfile.myimage

This way there is no git, git-lfs, or openssh-client in the final container and no leakage of ssh credentials. I could reasonably add anything this way, separating build image and deploy image. Thanks for all the help!

@jourdain
Copy link
Collaborator

That solution seems reasonable and indeed we should not ignore the regular docker capabilities.

We obviously try to streamline most of what we can, but your solution remains simple and reasonable.

@Besler Besler closed this as completed Jan 31, 2023
@psavery
Copy link
Collaborator

psavery commented Feb 1, 2023

@psavery The issue I ran into is that the build.sh script is ran with gosu trame-user, causing the ssh credentials to fail since the user must be root to interface with ssh. My simple solution was to bypass gosu and do a multi-stage build, resulting in one file:

My apologies! Earlier, I had meant to write RUN /opt/trame/build.sh instead of RUN /opt/trame/entrypoint.sh build for the very reasons you mentioned. But I'm glad you figured it out!

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

No branches or pull requests

3 participants