TL;DR;
If you're trying to test their knowledge of docker
then your Dockerfile
is already spoiled with common mistakes. If it's testing their knowledge of whatever is running inside the container created from an image built from your Dockerfile
then it depends on what the application does and if you're trying to test them on their capabilities of debugging an application in general then the sky is the limit on how many hoops you can make them jump from incorrect binaries for the OS, incorrect file permissions, encoding issues, resource allocation, networking, ...
Current common mistakes
- "Split long or complex RUN statements on multiple lines separated with backslashes ..."
- Pin the version of the
apt
packages that you're installing (note: this is by far the most common mistake I see)
- Don't install packages recommended by
apt
that you do not need
- "When you clean up the apt cache by removing /var/lib/apt/lists it reduces the image size ..."
- "the instructions
RUN
, COPY
, ADD
create layers" and the WORKDIR
instruction will create the directory if it doesn't already exist - removing the RUN mkdir app
removes a layer from the final image
- Pin the version of
gem
packages
- Chain commands in the
RUN
instruction to reduce the amount of layers in the final image
- Set the
ENTRYPOINT
instruction in your Dockerfile
- Use JSON notation for
CMD
and ENTRYPOINT
arguments
Note: debain
based images perform cleanup after every apt-get install
but hadolint
will complain if you don't explicitly remove the apt
files. You can either ignore the linting error or explicitly cleanup after the install, I prefer the latter.
A hadolint
'd version of your Dockerfile
:
FROM ruby:2.7.1
RUN apt-get update && \
apt-get install -y --no-install-recommends \
nodejs=10.21.0~dfsg-1~deb10u1 && \
rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN gem install bundler:2.1.4 && \
bundle install
COPY . ./
EXPOSE 3000
ENTRYPOINT ["entrypoint.sh"]
CMD ["bundle", "exec", "rails", "s", "-p", "3000", "-b", "'0.0.0.0'"]
Concerning the docker-compose
configuration, setting the command
is redundant:
version: '3.8'
services:
app:
build: .
volumes:
- .:/app
ports:
- "3000:3000"
... regarding the ports being open it really depends on what your expectations are. If you're expecting the person to advise you that mapping ports is meh and that you should proxy traffic to the service (i.e. through nginx
) then yes that should be considered an issue.
Additional common mistakes
A non-exhaustive list of common mistakes I often come across:
COPY
'ing a tar
archive into an image then un-compressing the tar
in 2 instructions
COPY files.tar.gz /
RUN tar czvf files.tar.gz
Can be replaced with ADD
(removes a layer from the final image) i.e.: ADD files.tar.gz /
- Changing directories then uncompressing
tar
files
RUN cd / && tar xzvf files.tar.gz
Can change directories with tar
's -C
option before un-compressing the file i.e. tar -C / xzvf files.tar.gz
curl
'ing tar
files then un-compressing them in 2 RUN
's
RUN curl -Lo files.tar.gz https://example.com/files.tar.gz
RUN tar xzvf files.tar.gz
Can pipe
the curl
output into tar
in a single RUN
instruction i.e.: curl https://example.com/files.tar.gz | tar xzv
- Using
pipe
's without setting SHELL
options ^ should be:
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN curl https://example.com/files.tar.gz | tar -C / xzv
COPY
'ing things from a multi-staged build that shouldn't be copied into the final layer:
FROM debian:buster-slim as build
# build everything
FROM scratch as target
COPY --from=build /some/random/file .
COPY
'ing secrets into builds (use buildkit
and your ssh-agent
for cloning repositories in the build)