-1

I have a Dockerfile that a sed commend in it, but when I run it locally I get an error. Is Docker doing something I don't know about?

I think it is trying to add the .sh file in but can't confirm this

Dockerfile:

FROM mongo

...

RUN sed -i 's/#!\/bin\/bash/#!\/bin\/bash\n\/bootstrap_mongo_on_k8s.sh \&\n/' /usr/local/bin/docker-entrypoint.sh

Local result:

$ sed -i 's/#!\/bin\/bash/#!\/bin\/bash\n\/bootstrap_mongo_on_k8s.sh \&\n/' /usr/local/bin/docker-entrypoint.sh

sed: 1: “/Users/*******/dev/fe ...“: command a expects \ followed by text
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
MrPickles
  • 810
  • 1
  • 9
  • 27
  • BTW, silly question, but did you test that command against the same version of `sed` installed in your container? If you tested on Apple's `sed` and it's running in GNU's, or you tested in GNU's and it's running in Busybox, that can change things. My answer tells you how to make an arbitrary command line pass through Docker without being corrupted in the process, but that may not help if the command line isn't actually *correct*. – Charles Duffy May 15 '19 at 16:51
  • @CharlesDuffy that was not a sill question at all. After leaving this over the weekend, I trying the command again and it worked (in the container). So it was a Version thing after all. – MrPickles May 20 '19 at 14:34
  • It would probably be less version-dependent (aka easier to implement only POSIX-specified features) to write the operation as an unconditional insert at line 2, rather than a replacement with a multi-line component at line 1. – Charles Duffy May 20 '19 at 14:48
  • See f/e https://stackoverflow.com/questions/6537490/insert-a-line-at-specific-line-number-with-sed-or-awk – Charles Duffy May 20 '19 at 14:49
  • Thanks that would have been a good idea, and I may look into that. But its an existing codebase with not funds to fix right now :( – MrPickles May 21 '19 at 09:22
  • Take a look at how my answer is amended to do that insert -- it's not something you need funds for. – Charles Duffy May 21 '19 at 13:53

1 Answers1

2

sed-Specific Advice: Use An Insert, Not A Replace

The below still assumes an implementation of the nonstandard -i option compatible with GNU sed.

RUN sed -i -e '2i/bootstrap_mongo_on_k8s.sh &' /usr/local/bin/docker-entrypoint.sh

...or, if formulated using the below advice:

RUN ["sed","-i","-e","2i/bootstrap_mongo_on_k8s.sh &","/usr/local/bin/docker-entrypoint.sh"]

General Advice: Passing Commands Through Docker Safely

Generally, the safest way to pass exact content to a RUN command is as a JSON list.

If the original, tested shell command you want to run in Docker is:

sed -i 's/#!\/bin\/bash/#!\/bin\/bash\n\/bootstrap_mongo_on_k8s.sh \&\n/' /usr/local/bin/docker-entrypoint.sh

...the literal strings it's composed of are, one per line, as follows:

  • sed
  • -i
  • s/#!\/bin\/bash/#!\/bin\/bash\n\/bootstrap_mongo_on_k8s.sh \&\n/
  • /usr/local/bin/docker-entrypoint.sh

As a JSON list, this would be:

["sed","-i","s/#!\\/bin\\/bash/#!\\/bin\\/bash\\n\\/bootstrap_mongo_on_k8s.sh \\&\\n/","/usr/local/bin/docker-entrypoint.sh"]

Note the doubled backslashes. This can be generated with a command of the form:

printf '%s\n' \
    sed \
    -i \
    's/#!\/bin\/bash/#!\/bin\/bash\n\/bootstrap_mongo_on_k8s.sh \&\n/' /usr/local/bin/docker-entrypoint.sh \
  | jq -Rnc '[inputs]'
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • 2
    I'd switch delimiters to get rid of all the `\/`. – Benjamin W. May 15 '19 at 16:14
  • 1
    I agree that that's the better approach for `sed` specifically. OTOH, the nice thing about letting `jq` convert a command line to a JSON string is that it'll work for anything that *did* work as an original shell command line (well, in this formulation, so long as that original didn't contain literal newlines). – Charles Duffy May 15 '19 at 16:41