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 <[email protected]>
RUN echo "http://dl-4.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
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.
-
\$\begingroup\$ Some points I'm thinking about are creating and running under a different user, volume for /root/.composer, docker-entrypoint.sh rather than composer-wrapper, and just read only mounting all of ~/.ssh. \$\endgroup\$Samuel Parkinson– Samuel Parkinson2016年02月19日 00:40:50 +00:00Commented Feb 19, 2016 at 0:40
1 Answer 1
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 ... >> /etc/apk/repositories && 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 &&
, 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...)
-
\$\begingroup\$ Great point on the wrapper script, there's no guarantee where the command will be, but I should be breaking out once it's found! For you second point, I'm using
&&
to chain a bunch of work together, rather than using separateRUN
commands that create more layers in the final image. Looking at it now, the secondRUN
I think should be merge in. Finally, I could well do, but I can't see a convention of it yet. Having the instructions in the file makes them more accessible in Docker Hub though. Thanks! \$\endgroup\$Samuel Parkinson– Samuel Parkinson2016年02月21日 10:44:37 +00:00Commented Feb 21, 2016 at 10:44 -
1\$\begingroup\$ Good to know that about
RUN
, I learned something, thanks! \$\endgroup\$janos– janos2016年02月21日 10:46:05 +00:00Commented Feb 21, 2016 at 10:46