Yogesh Kushwaha
Yogesh Kushwaha

Reputation: 149

How to replace a text in conf file in docker image

I am trying to build a Docker image, where I need to get list of directories separated by comma under a parent directory and set that in a configuration file copied in the container but the text is never replaced in conf file. below is the docker image. or Github Link

FROM ubuntu:16.04
LABEL maintainer="TEST"

RUN apt-get update && apt-get install vim git -y

COPY odoo.conf /etc/odoo/odoo.cfg

RUN git clone https://github.com/kelseyhightower/helloworld.git /mnt/extra-addons/hellow-world1
RUN git clone https://github.com/kelseyhightower/helloworld.git /mnt/extra-addons/hellow-world2
RUN git clone https://github.com/kelseyhightower/helloworld.git /mnt/extra-addons/hellow-world3
RUN git clone https://github.com/kelseyhightower/helloworld.git /mnt/extra-addons/hellow-world4

COPY setup.sh /setup.sh
RUN ["chmod", "+x", "/setup.sh"]
CMD ["/setup.sh"]

the search and replace thing happens in setup.sh but entering in shell never shows the replacement. however, if I execute the command /setup.sh in container shell it does the job.

Interested to know, how to do that and what I am doing wrong?

setup.sh

# get addons path
addons_path=`ls -d /mnt/extra-addons/* | paste -d, -s`
# can't use / because directory name contains, using #
sed -i -e "s#__addons__path__#${addons_path}#" /etc/odoo/odoo.cfg

/etc/odoo/odoo.conf

[options]
addons_path = __addons__path__
data_dir = /var/lib/odoo
.......

Expected /etc/odoo/odoo.conf

[options]
addons_path = /mnt/extra-addons/hellow-world1,/mnt/extra-addons/hellow-world2,/mnt/extra-addons/hellow-world3,/mnt/extra-addons/hellow-world4
data_dir = /var/lib/odoo

## Update I removed intermediate setup.sh and doing whole thing in Dockerfile which looks like

FROM ubuntu:16.04
LABEL maintainer="TEST"

RUN apt-get update && apt-get install vim git -y

COPY odoo.conf /etc/odoo/odoo.cfg

RUN git clone https://github.com/kelseyhightower/helloworld.git /mnt/extra-addons/hellow-world1
RUN git clone https://github.com/kelseyhightower/helloworld.git /mnt/extra-addons/hellow-world2
RUN git clone https://github.com/kelseyhightower/helloworld.git /mnt/extra-addons/hellow-world3
RUN git clone https://github.com/kelseyhightower/helloworld.git /mnt/extra-addons/hellow-world4
ENV addons_path=$(ls -d /mnt/extra-addons/* | paste -d, -s)  ## Fails here it sets blank so sed command works but the variable addons_path doesn't have the value probably I am defining variable wrongly?
RUN sed -i -e "s#__addons__path__#$addons_path#" /etc/odoo/odoo.cfg

Upvotes: 2

Views: 9064

Answers (3)

BMitch
BMitch

Reputation: 263469

Containers are a wrapper around running a process (that wrapper being namespaces and cgroups). The process being run is defined by the ENTRYPOINT and CMD lines of a Dockerfile. You can override the image's default process to run when you run the container, and for the value of CMD, overriding involves passing a different command after the image name.

So when you're Dockerfile ends with:

COPY setup.sh /setup.sh
RUN ["chmod", "+x", "/setup.sh"]
CMD ["/setup.sh"]

You have defined the default value for CMD in your image. But when you run:

docker build -t docker-test .; docker run -it docker-test bash

The ./setup.sh CMD value is replaced by bash. This means setup.sh is never run.


You can solve this several ways.

  1. You can run your setup.sh as part of the image build. If the script has no dependencies on how the container is being run (e.g. external volumes, environment variables passed in, etc), then this is the better choice.

  2. Move your script to an entrypoint and have it finish by running the command provided. When you define both an entrypoint and a cmd, a container is only going to run a single process, so the behavior of docker is to pass the cmd as arguments to the entrypoint. To run the cmd, you need to do that as part of your entrypoint script.


Option #1 looks like the solution you have done, and the answer I'd recommend:

COPY setup.sh /setup.sh
RUN ["chmod", "+x", "/setup.sh"]
RUN ["/setup.sh"]
CMD bash

You'll want to include the shell at the top of the script so linux knows how to run it:

#!/bin/sh
# The #!/bin/sh above is important, you can also replace that with the path to bash
# get addons path
addons_path=`ls -d /mnt/extra-addons/* | paste -d, -s`
# can't use / because directory name contains, using #
sed -i -e "s#__addons__path__#${addons_path}#" /etc/odoo/odoo.cfg

Option #2 is useful if /mnt/extra-addons/ changes every time you run the container. This looks like:

COPY setup.sh /setup.sh
RUN ["chmod", "+x", "/setup.sh"]
ENTRYPOINT ["/setup.sh"]
CMD ["bash"]

With an additional line added to the setup script:

#!/bin/sh
# get addons path
addons_path=`ls -d /mnt/extra-addons/* | paste -d, -s`
# can't use / because directory name contains, using #
sed -i -e "s#__addons__path__#${addons_path}#" /etc/odoo/odoo.cfg

# this next line runs the passed arguments as pid 1, replacing this script
# this is how you run an entrypoint and fall through to a cmd
exec "$@"

Upvotes: 0

Yogesh Kushwaha
Yogesh Kushwaha

Reputation: 149

I think the trick was to execute .sh file

Not working

CMD ["/setup.sh"]

Working

RUN /bin/bash -c "/setup.sh"

Final Result

FROM ubuntu:16.04
LABEL maintainer="TEST"

RUN apt-get update && apt-get install vim git -y

COPY odoo.conf /etc/odoo/odoo.cfg

RUN git clone https://github.com/kelseyhightower/helloworld.git /mnt/extra-addons/hellow-world1
RUN git clone https://github.com/kelseyhightower/helloworld.git /mnt/extra-addons/hellow-world2
RUN git clone https://github.com/kelseyhightower/helloworld.git /mnt/extra-addons/hellow-world3
RUN git clone https://github.com/kelseyhightower/helloworld.git /mnt/extra-addons/hellow-world4
#ENV addons_path=$(ls -d /mnt/extra-addons/* | paste -d, -s)
#RUN sed -i -e "s#__addons__path__#NEW_PATH#" /etc/odoo/odoo.cfg

COPY setup.sh /setup.sh
RUN ["chmod", "+x", "/setup.sh"]
RUN /bin/bash -c "/setup.sh"

Upvotes: 0

KamilCuk
KamilCuk

Reputation: 140880

Try this:

addons_path=$(find /mnt/extra-addons/ -type d -maxdepth 1 | tr '\n' ',')
sed -i -e "s#__addons__path__#${addons_path}#" /etc/odoo/odoo.cfg
  1. This will not work if the file names contain # or newlines.
  2. paste joins two streams into one. You have just one stream. Use tr for example to substitute newline for another character.
  3. Don't parse ls output.
  4. Syntax using ` ` is deprecated, use $( ... ).

Upvotes: 3

Related Questions