chainguard-images / images

Public Chainguard Images
https://chainguard.dev/chainguard-images
Apache License 2.0
543 stars 140 forks source link

Bash image not handling arguments #923

Open amouat opened 1 year ago

amouat commented 1 year ago

Which image/versions are related to this issue/feature request?

cgr.dev/chainguard/bash

Issue/Feature description

I'd expect this to work:

$ docker run cgr.dev/chainguard/bash echo hello world

The arguments to echo get swallowed for some reason. The same thing happens with other commands e.g. uname -a

Fixing this is annoyingly not straightforward. There are two choices I can see:

  1. Remove entrypoint and symlink /bin/sh to /bin/bash. That way the default container command handling will kick in, which correctly handles the above, but assumes the shell is at /bin/sh
  2. Write an entrypoint script similar to the one for Docker Hub official bash image.
marshall007 commented 2 months ago

Lack of convenient args handling is present in all images, not just cgr.dev/chainguard/bash. It would be great if we could add the proposed entrypoint.sh wrapper to all such "utility" images.

Presently, Chainguard images cannot be used as drop-in replacements for initContainers in helm charts with hard-coded command: ["sh", "-c", ...] style arguments. Here is an example from the mattermost-enterprise-edition chart where you'd ideally be able to drop in cgr.dev/chainguard/curl: https://github.com/mattermost/mattermost-helm/blob/02228aa9356b2a86d39aede9d09d0af3de6d5e26/charts/mattermost-enterprise-edition/templates/deployment-mattermost-app.yaml#L61-L82

Also some additional variations on the entrypoint.sh wrapper I have seen in the wild:

via tianon/docker-bash (linked in OP):

#!/usr/bin/env bash
set -Eeuo pipefail

# first arg is `-f` or `--some-option`
# or there are no args
if [ "$#" -eq 0 ] || [ "${1#-}" != "$1" ]; then
    # docker run bash -c 'echo hi'
    exec bash "$@"
fi

exec "$@"

via curlimages/curl:

#!/bin/sh
set -e

if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ]; then
  set -- curl "$@"
fi

exec "$@"

via appropriate/docker-curl:

#!/bin/sh
set -e

# Prepend "curl" if the first argument is not an executable
if ! type -- "$1" &> /dev/null; then
    set -- curl "$@"
fi

exec "$@"
xnox commented 2 months ago

For bash image sounds like we should add bash-binsh package to it.

For curl not sure if we want to keep curl:latest without any shell and have separate curl-docker:latest that has shell and does args mangling as the other curl images do. Unless we are loosing the battle of shell less images.

Any idea which helm charts expect curl images with shell and if we can improve those to not need shell?

amouat commented 2 months ago

I did some work on this previously and created https://github.com/wolfi-dev/container-entrypoint/, the idea being it could be added as a package to any containers with a shell to mimic this functionality.

marshall007 commented 2 months ago

@xnox maybe we could create small binary to serve as the entrypoint and performs similar args manipulation and calls exec(...) even if a shell is not available? Like what @amouat put together but without the shell dependency.

For example, here is an shell interpreter written in Go that implements the type and exec built-ins: https://github.com/mvdan/sh/blob/793d36450a0a5a466199b04c458fb4a1202cf641/interp/builtin.go#L249-L332

This is obviously much too heavy a solution to use off the shelf, and maybe not worth doing at all, but it would be great if you could exec any program in a distroless (or dev) images by overriding the command args.