Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RUN inside a conditional statement in Dockerfile

Tags:

docker

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.

like image 322
BeeNag Avatar asked Jul 25 '18 11:07

BeeNag


People also ask

Can we use if else in Dockerfile?

Accepted answer does not cover "if else condition" part of the question. Would be better to rename it to "Dockerfile with external arguments" if condition check didn't mean to be a requirement.

Can Dockerfile run 2 commands?

There can only be one CMD instruction in a Dockerfile. If you list more than one CMD then only the last CMD will take effect. If CMD is used to provide default arguments for the ENTRYPOINT instruction, both the CMD and ENTRYPOINT instructions should be specified with the JSON array format.

How do I create a Run command in Dockerfile?

The basic syntax for the command is: docker run [OPTIONS] IMAGE [COMMAND] [ARG...] You can run containers from locally stored Docker images. If you use an image that is not on your system, the software pulls it from the online registry.

Can I have ENTRYPOINT and CMD in Dockerfile?

Using ENTRYPOINT or CMD Both ENTRYPOINT and CMD are essential for building and running Dockerfiles—it simply depends on your use case. As a general rule of thumb: Opt for ENTRYPOINT instructions when building an executable Docker image using commands that always need to be executed.


1 Answers

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" .
like image 84
Bernard Avatar answered Nov 10 '22 08:11

Bernard