A Dockerfile for Composer (a dependency manager for PHP) I recently built a Docker image for Composer. I'd love to get a review of the image, the Bash based wrapper script, its recommended use, and the repository structure.

Here's the Dockerfile for the latest tag:

FROM alpine:edge

MAINTAINER Samuel Parkinson &lt;sam@graze.com&gt;

RUN echo "http://dl-4.alpinelinux.org/alpine/edge/testing" &gt;&gt; /etc/apk/repositories &amp;&amp; \
    apk add --no-cache \
    ca-certificates \
    git \
    mercurial \
    subversion \
    php7 \
    php7-curl \
    php7-json \
    php7-openssl \
    php7-phar \
    php7-posix

RUN /usr/bin/php7 -r "readfile('https://getcomposer.org/installer');" | \
    /usr/bin/php7 -- --install-dir=/usr/local/bin --filename=composer

COPY ./composer-wrapper /usr/local/bin/composer-wrapper

VOLUME ["/usr/src/app", "/root/.composer"]

WORKDIR /usr/src/app

ENTRYPOINT ["/usr/local/bin/composer-wrapper"]


The wrapper script, which adds the --ignore-platform-reqs flag for supported commands, so that users don't have to do it themselves as the image doesn't contain many of the common php extensions library's require:

#!/bin/sh

# Loop over each argument.
for argument in "$@"; do
    case "$argument" in
        # Append the argument if the command matches one we need to use `--ignore-platform-reqs` with.
        # Found using the following search: https://github.com/composer/composer/search?q=ignore-platform-reqs+path%3Asrc%2FComposer%2FCommand%2F
        # Uses `set` to update the arguments, see https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html.
        create-project|install|remove|require|update) set -- --ignore-platform-reqs "$@";;

        # Otherwise just pass it on.
        *) ;;
    esac
done

# Call composer with the updated arguments.
exec /usr/bin/php7 /usr/local/bin/composer "$@"


The recommended way to use the image, mounting the source and composer user folder, and read only mounting the users ssh key for use when using git based dependencies:

docker run --rm -it \
    -v $(pwd):/usr/src/app \
    -v ~/.composer:/root/.composer \
    -v ~/.ssh:/root/.ssh:ro \
    graze/composer


And finally the repository itself (which includes tests of the image!):

https://github.com/graze/docker-composer

I'm no expert at bash, and pretty new to Docker too so I'd love to know if there's anything I'm missing, or anything I'm doing that's unconventional.
In the wrapper script,
I don't understand why you need to loop over each argument.
Wouldn't it be enough to use a case "$1" in ... without looping at all?

If you really do need to loop,
for example to make it work even if the command you want to match is not in the first position sometimes,
then I think you want to break out of the loop after finding a match. That is:

# Loop over each argument.
for argument in "$@"; do
    case "$argument" in
        # Append the argument if the command matches one we need to use `--ignore-platform-reqs` with.
        # Found using the following search: https://github.com/composer/composer/search?q=ignore-platform-reqs+path%3Asrc%2FComposer%2FCommand%2F
        # Uses `set` to update the arguments, see https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html.
        create-project|install|remove|require|update) set -- --ignore-platform-reqs "$@"
        break
        ;;

        # Otherwise just pass it on.
        *) ;;
    esac
done


Another small thing,
at the top of the Dockerfile,
I find the echo ... &gt;&gt; /etc/apk/repositories &amp;&amp; apk add ... a bit curious.
Under what circumstances might that appending with echo fail?
And why not check the exit code of the other commands that follow?
It seems that either all commands should be chained with &amp;&amp;, or none of them.

Lastly, I have very minimal experience with Docker,
but I'm wondering if instead of multiple RUN commands,
wouldn't it be better to put them in a single shell script,
and RUN that script instead.
(That's not a recommendation, just a general wondering...)