4
\$\begingroup\$

I'm getting started with Docker, and I've set up a very simple image built from a Dockerfile. It's based FROM the ubuntu image, and I'm downloading and building apache from source.

I'm just curious if I'm on the right tracks, if there's a more "Docker" way of doing what I'm doing, or any other things that I could be doing different/better.

It's running in the default VM that Kitematic adds for me, and I'm building the image with docker build -t webserver ., then testing with docker run -p 80:80 -i -t webserver /bin/bash

FROM ubuntu:latest
RUN apt-get -qq update -y
RUN apt-get -qq install build-essential -y
RUN mkdir install-files
WORKDIR /install-files
RUN mkdir apache
WORKDIR /install-files/apache
RUN apt-get -qq install wget -y >/dev/null
RUN wget http://mirrors.ukfast.co.uk/sites/ftp.apache.org//apr/apr-1.5.2.tar.gz >/dev/null
RUN tar -xvzf apr-1.5.2.tar.gz >/dev/null
WORKDIR /install-files/apache/apr-1.5.2
RUN ./configure >/dev/null
RUN make >/dev/null
RUN make install >/dev/null
WORKDIR /install-files/apache
RUN wget http://apache.mirror.anlx.net//apr/apr-util-1.5.4.tar.gz >/dev/null
RUN tar -xvzf apr-util-1.5.4.tar.gz >/dev/null
WORKDIR /install-files/apache/apr-util-1.5.4
RUN ./configure --with-apr=/usr/local/apr/ >/dev/null
RUN make >/dev/null
RUN make install >/dev/null
WORKDIR /install-files/apache/
RUN apt-get -qq install libpcre3 libpcre3-dev >/dev/null
RUN wget http://mirror.ox.ac.uk/sites/rsync.apache.org//httpd/httpd-2.4.18.tar.gz >/dev/null
RUN tar -xvzf httpd-2.4.18.tar.gz >/dev/null
WORKDIR /install-files/apache/httpd-2.4.18
RUN ./configure --with-apr=/usr/local/apr/ >/dev/null
RUN make >/dev/null
RUN make install >/dev/null
RUN mkdir /tech
RUN ln -s /usr/local/apache2/ /tech/httpd
RUN apt-get -qq install nano -y
ADD startup.sh /root/startup.sh
RUN chmod 777 /root/startup.sh
WORKDIR /
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Jan 13, 2016 at 23:50
\$\endgroup\$

3 Answers 3

4
\$\begingroup\$

Do you really have a good reason for this permission setup?

RUN chmod 777 /root/startup.sh

It's a bit ironic to use the -v flag of tar, and then redirecting the output to /dev/null here:

RUN tar -xvzf httpd-2.4.18.tar.gz >/dev/null

You can drop that flag and the redirection, the outcome should be the same.


I'm not very familiar with Docker, but I'm wondering what will happen if any of the commands fail. For example, if make fails, you probably don't want to run the make install command that follows it. I don't have a solution for that, but error handling is something to think about.


The repetitive redirections and duplicated strings don't look pretty, and look hard to maintain. There gotta be a better way. Perhaps you could put the shell commands into a proper .bash script, enjoy all the power of regular bash scripting (variables, functions), and in the docker file just fetch that script using wget, and then execute it.

answered Jan 14, 2016 at 0:33
\$\endgroup\$
3
\$\begingroup\$

A few comments:

  • I’m not sure why you’re so keen to suppress any and all output from your RUN commands. That information can be useful when you’re trying to work out why your image hasn’t built properly. It can be a bit verbose when it goes fine, but it’s useful when it fails.

    (Docker’s inbuilt networking is sometimes a bit flakey for me, and apt-get and yum just fail when trying to retrieve indexes. Being able to see their output as they can’t connect out is always useful.)

  • No comments! A Dockerfile should be treated like any other piece of code. There should be comments explaining why it was written this way, what the intended outcome is, and so on. This file could be quite hard to maintain.

    For example, there are a couple of hard-coded URLs to mirrors that pull tarfiles. Here are some maintenance questions that comments might help me answer:

    • When should I rev the version numbers in those URLs? I don’t want to be getting insecure versions of packages.
    • Where should I look for an alternative if those mirrors go away?
    • What are these packages for? When can I know if I don’t need them any more?

  • Each line in a Dockerfile adds a new layer to the image’s filesystem, so you want to avoid creating unnecessary layers. For example, four lines at the top of the first block can be condensed into two:

    RUN mkdir -p /install-files/apache
    WORKDIR /install-files/apache
    

    You could also use the -O flag of wget to avoid having to cut out the first WORKDIR line.

  • You’re installing nano and wget with apt-get, but it’s not obvious why. I feel like the former could be replaced with curl (which is built-in), and if you ever need a text editor inside your container, install it when you need it. Don’t fill your container with things you don’t need.

answered Jan 14, 2016 at 8:36
\$\endgroup\$
1
  • \$\begingroup\$ WORKDIR will create the directories if they do not already exist, the RUN mkdir ... instructions can be removed entirely. \$\endgroup\$ Commented Oct 31, 2019 at 14:13
2
\$\begingroup\$

Old question but you can do a lot to reduce the size of your final image (RUN, COPY and ADD create layers).

Here's my version, with specific observations as comments:

# I would suggest pinning a specific version of the image that you're extending
# ubuntu:latest today may not be the same as ubuntu:latest tomorrow
FROM ubuntu:18.04
# combining the apt-get update and install RUN instructions removes layers
# all packages that you need can be installed in the same RUN (using curl instead of wget)
RUN apt-get -qq update -y && \
 apt-get -qq install -y \
 build-essential \
 curl \
 libpcre3 \
 libpcre3-dev \
 nano
# WORKDIR will create the directories if they do not already exist
# removing the RUN's removes an additional 2 layers
WORKDIR /install-files/apache/apr-1.6.5
# combine the curl | tar RUN instructions (note: versions updated)
# install apr, expat, apr-utils and httpd in a condensed fashion and purge the installation files
# the final image is 374MB without the installation files, 468MB with the installation files
RUN curl -L http://mirrors.ukfast.co.uk/sites/ftp.apache.org/apr/apr-1.6.5.tar.gz | tar xvz -C /install-files/apache && \
 ./configure && \
 make && \
 make install && \
 rm -rf /install-files/apache/apr-1.6.5
WORKDIR /install-files/apache/expat-2.2.9
RUN curl -L https://github.com/libexpat/libexpat/releases/download/R_2_2_9/expat-2.2.9.tar.gz | tar xvz -C /install-files/apache && \
 ./configure && \
 make && \
 make install && \
 rm -rf /install-files/apache/expat-2.2.9
WORKDIR /install-files/apache/apr-util-1.6.1
RUN curl -L http://mirrors.ukfast.co.uk/sites/ftp.apache.org/apr/apr-util-1.6.1.tar.gz | tar xvz -C /install-files/apache && \
 ./configure --with-apr=/usr/local/apr/ && \
 make && \
 make install && \
 rm -rf /install-files/apache/apr-util-1.6.1
WORKDIR /install-files/apache/httpd-2.4.41
RUN curl http://mirror.ox.ac.uk/sites/rsync.apache.org//httpd/httpd-2.4.41.tar.gz | tar xvz -C /install-files/apache && \
 ./configure --with-apr=/usr/local/apr --with-expat=/usr/local/expat && \
 make && \
 make install && \
 rm -rf /install-files/apache/httpd-2.4.41
WORKDIR /
RUN mkdir /tech && \ 
 ln -s /usr/local/apache2/ /tech/httpd
# 1. "Although ADD and COPY are functionally similar, generally speaking, COPY is preferred."
# https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#add-or-copy
# 2. It's common practice to name the entrypoint script "docker-entrypoint.sh"
# 3. would suggest following the principle of least privilege
# https://digitalguardian.com/blog/what-principle-least-privilege-polp-best-practice-information-security-and-compliance
# COPY preserves file permissions - set them on the host and remove the chmod layer altogether
COPY docker-entrypoint.sh /root
# finally, our ENTRYPOINT
ENTRYPOINT ["/root/docker-entrypoint.sh"]
Toby Speight
87.1k14 gold badges104 silver badges322 bronze badges
answered Oct 31, 2019 at 15:06
\$\endgroup\$
3
  • \$\begingroup\$ @TobySpeight "you can do a lot to reduce the size of your final image" is what prompted me to write this version. "the final image is 374MB without the installation files, 468MB with the installation files" is an improvement over the original along with all the best practices - e.g. the review is in-line as comments in the Dockerfile... \$\endgroup\$ Commented Nov 1, 2019 at 9:56
  • 1
    \$\begingroup\$ Ah, I've just realised that you hid your review in the comments of your replacement! That wasn't obvious (and not the usual way to review), so I've edited your answer to make it clearer. \$\endgroup\$ Commented Nov 1, 2019 at 11:26
  • \$\begingroup\$ Thanks for the edit. I intentionally put them in-line as per the comment here: "No comments! A Dockerfile should be treated like any other piece of code. There should be comments explaining why it was written this way ...". \$\endgroup\$ Commented Nov 1, 2019 at 11:28

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.