2
\$\begingroup\$

I've create a Docker script momodock.script that does some installation for a set of tools that I'll need to install on multiple machines:

FROM ubuntu:latest
MAINTAINER Momo <mo@mo.com>
LABEL description="TL;DR instructions to install Moses with Docker."
RUN apt-get update
RUN apt-get install -y apt-utils debconf-utils
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
RUN apt-get update
RUN apt-get -y upgrade
RUN apt-get install -y sudo nano
RUN apt-get install -y perl 
RUN apt-get install -y python-dev python3-dev python-pip python3-pip
RUN apt-get install -y libboost-all-dev
RUN apt-get install -y build-essential git-core pkg-config automake libtool wget zlib1g-dev python-dev libbz2-dev
RUN apt-get install -y cmake 
RUN useradd -m -p mosesdocker -s /bin/bash ubiwan
RUN usermod -aG sudo ubiwan  # add user to sudo list
USER ubiwan
ENV HOME /home/ubiwan
WORKDIR $HOME
CMD /bin/bash
RUN cd $HOME
RUN git clone https://github.com/moses-smt/mosesdecoder.git 
WORKDIR $HOME/mosesdecoder
RUN make -f $HOME/mosesdecoder/contrib/Makefiles/install-dependencies.gmake
RUN ./compile.sh  --max-kenlm-order=20 --max-factors=1000
WORKDIR $HOME
RUN git clone https://github.com/moses-smt/mgiza.git
WORKDIR $HOME/mgiza/mgizapp
RUN cmake .
RUN make 
RUN make install
RUN cp $HOME/mgiza/mgizapp/scripts/merge_alignment.py bin/
WORKDIR $HOME
RUN git clone https://github.com/jonsafari/clustercat.git
WORKDIR $HOME/clustercat
RUN make -j 4
WORKDIR $HOME
RUN mkdir moses-training-tools
RUN cp mgiza/mgizapp/bin/* moses-training-tools/
RUN cp clustercat/bin/clustercat moses-training-tools/
RUN cp clustercat/bin/mkcls moses-training-tools/mkcls-clustercat
RUN mv moses-training-tools/mkcls moses-training-tools/mkcls-original
RUN cp moses-training-tools/mkcls-clustercat moses-training-tools/mkcls

And building it works smoothly:

docker build -t momo-docker.image - < momodock.script

But I've written the script like how one would emulate a human in the interactive docker environment.

Are there ways to simplify how I'm installing the required dependencies and software?

\$\endgroup\$
2
  • \$\begingroup\$ May be you can put all the RUN commands to a file and execute it as script? \$\endgroup\$ – dotslashlu Apr 7 '17 at 8:04
  • \$\begingroup\$ Your title should indicate the purpose of your code, rather than what you hope to learn from the review - see How to Ask. \$\endgroup\$ – Toby Speight Apr 7 '17 at 12:35
5
\$\begingroup\$

First off, a little theory. Docker uses most of its RUN commands very similar to what git is doing with commits. That said it makes sense to put RUN commands together that change the state of the image.

By the way, just like in git you can also go back any step in Docker.

According to the Dockerfile reference on RUN the string after RUN is appended to /bin/sh -c on Linux. This means you can chain commands using the usual semicolon (;) and double ampersand (&&) operators. Example:

RUN cmake . && make && make install

Hint: The difference between the semicolon and double ampersand is that a semicolon only separates commands on one line whereas the latter will run the righthand side command only if the lefthand side is successful.

Additionally commands like apt-get install allow you to install multiple packages at once, which you actually used a few times already:

RUN apt-get install pkg1 pkg2 pkg3

If the lines get too long, you can use the backslash character (\) at the end of a line to mark a line break. Example:

RUN apt-get install pkg1 pkg2 \
pkg3 pkg4 pkg5

Another way to optimise the image is getting rid of the copy statements and use symlinks instead

Aside from that your Docker file looks good.

If you expect to have variations of the process anytime in the future, consider splitting it into a base image and specialized images that rely on the base.

\$\endgroup\$
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.