9

So I am trying to make a basic Dockerfile, but when I run this it says

The command bin/sh -c sudo apt-get install git python-yaml python-jinja2 returned a non-zero code: 1

My question is what am I doing wrong here, and is it even allowed to do commands like 'cd' and 'source' from the Dockerfile?

FROM Ubuntu
MAINTAINER example

#install and source ansible
RUN sudo apt-get update
RUN sudo apt-get install git python-yaml python-jinja2 python-pycurl
RUN sudo git clone https://github.com/ansible/ansible.git
RUN sudo cd ansible
RUN sudo source ./hacking/env-setup
stephan
  • 2,293
  • 4
  • 31
  • 55

2 Answers2

21

Couple of pointers / comments here:

  • It's ubuntu not Ubuntu
  • From base ubuntu (and unfortunately, a lot of images) you don't need to use sudo, the default user is root (and in ubuntu, sudo is not included anyway)
  • You want your apt-get update and apt-get install to be RUN as part of the same command, to prevent issues with Docker's layer cache
  • You need to use the -y flag to apt-get install as the Docker build process runs non-interactively
  • Few other points I could make about clearing up your apt-cache and other non-required artifacts after running the commands, but this should be enough to get going on

New Dockerfile (taking into account the above) would look something like:

FROM ubuntu
MAINTAINER example

#install and source ansible
RUN apt-get update && apt-get install -y \
    git \
    python-yaml \
    python-jinja2 \
    python-pycurl

RUN git clone https://github.com/ansible/ansible.git
WORKDIR ansible/hacking
RUN chmod +x env-setup; sync \
    && ./env-setup

You might also find it useful to read the Dockerfile best practises.

Edit: Larsks answer also makes some useful points about the state of the container not persisting between layers so you should go upvote him too!

Community
  • 1
  • 1
johnharris85
  • 17,264
  • 5
  • 48
  • 52
  • 1
    Why not? It's another layer but it's no-op. It makes it more explicit for someone to read seeing which directory we're currently working in, rather than having to parse a load of `RUN` statements to see if there are `cd`s in there. – johnharris85 Oct 27 '16 at 14:33
  • Ok but this will not work if we clean all temp files (cache ...) at the end, because the final image will contain all the layers including the layer where the cache was not cleaned. So it works here but you must pay attention that each layers will be in the final image. – Paul Trehiou Oct 27 '16 at 15:01
  • Paul, explain? I'm saying clean the apt-cache and etc at the end of the `RUN apt-get update...` instruction. Then they will not persist (as they are added _and_ removed before the layer is committed). – johnharris85 Oct 27 '16 at 15:30
  • Yes that's OK. You said "after running the commands" so I thought you mean at the end of the Dockerfile – Paul Trehiou Oct 27 '16 at 15:38
4

When building an image you're already running as root. You don't need sudo and there's a good chance it's not installed.

Along similar lines, this will never work:

RUN sudo cd ansible

The cd command only affects the current process; this would run cd and then exit, leaving you in the same directory you started in. The Docker WORKDIR directive can be used to persistently change the working directory:

WORKDIR ansible

You can also pass a series of shell commands to the RUN directive, like this:

RUN cd ansible; source ./hacking/env-setup

But even that probably won't do what you want, because like the sudo cd ... command earlier, that would modify your environment...and then exit, leaving the current environment unchanged in any subsequent commands.

If you want to run Ansible in a container, you should probably either install it, or plan to run the env-setup script manually after starting a container from the image.

larsks
  • 277,717
  • 41
  • 399
  • 399