32

I have a Dockerfile which currently uses the following:

COPY ./compose/local/django/start.sh /start.sh
RUN sed -i 's/\r//' /start.sh
RUN chmod +x /start.sh

As you can see it copies the file and then makes it executable. I now need to change this depending on a argument provided when I build the image. I have tried using this:

RUN if [ "$arg" = "True" ]; then \
    COPY ./compose/local/django/new.sh /new.sh \
    RUN sed -i 's/\r//' /new.sh \
    RUN chmod +x /new.sh; else \
    COPY ./compose/local/django/start.sh /start.sh \
    RUN sed -i 's/\r//' /start.sh \
    RUN chmod +x /start.sh; fi

But this fails as it appears that I can't run COPY or RUN commands inside a conditional statement. It always fails with:

/bin/sh: 1: COPY: not found

or

/bin/sh: 1: RUN: not found

So, I think that the best course of action is to create a separate bash file which does the copies, something like:

#!/usr/bin/env bash

if [ "${arg}" = "True" ]; then
    echo "arg = ${arg}"
    cp ./compose/local/django/new.sh /new.sh
elif [ "${arg}" = "False" ]; then
    echo "arg = ${arg}"
    cp ./compose/local/django/start.sh /start.sh
fi

But I am struggling with how to make the copied bash files executable. I know I can do it by running chmod +x in the command line, but as I am not the only person who is going to be building this, I was hoping that there would be a better solution, something like I was doing previously in the original Dockerfile script.

Can anyone help me with this? Any help would be much appreciated.

BeeNag
  • 1,764
  • 8
  • 25
  • 42
  • here is the similar question, with many solutions - https://stackoverflow.com/questions/43654656/dockerfile-if-else-condition-with-external-arguments let me know if any works for you? – Rohan J Mohite Jul 25 '18 at 13:11
  • @RohanJMohite I based the second part of my question on that answer (i.e. creating a separate bash file). I just don't want to have to use the command line to make it executable, as there will be more than one person using it so it gets a bit laborious if they have to do it themselves when they want to use it. – BeeNag Jul 25 '18 at 14:19
  • 1
    If you look at 1st answer https://stackoverflow.com/questions/43654656/dockerfile-if-else-condition-with-external-arguments, I think this is what you were looking for. – Rohan J Mohite Jul 25 '18 at 14:37
  • Possible duplicate of [Dockerfile if else condition with external arguments](https://stackoverflow.com/questions/43654656/dockerfile-if-else-condition-with-external-arguments) – Matt S Jul 25 '18 at 18:37

1 Answers1

74

Use only one 'RUN' statement. It's a best practice as it will reduce the size taken by your image.

This is how you can pass an argument to docker build.

Dockerfile:

...
ARG NEW
COPY ./compose/local/django/new.sh /new.sh
COPY ./compose/local/django/start.sh /start.sh

RUN if [ "$NEW" = "True" ]; then \
    sed -i 's/\r//' /new.sh && \
    chmod +x /new.sh; \
  else \
    sed -i 's/\r//' /start.sh && \
    chmod +x /start.sh; \
  fi

and build it like this

docker build --build-arg NEW="True" .
Bernard
  • 16,149
  • 12
  • 63
  • 66