Home > other >  Cat in script in docker
Cat in script in docker

Time:05-18

I have a container with node:18-alpine3.14 as base image. I have docker-compose file with

command: ["prepare_config.sh","--","npm", "run", "start-p"]

in prepare config

#!/bin/bash
json_data=$(cat <<EOF
{
    "url": "$URL"
}
EOF
)
echo "$json_data";

When I try to run this code I get error

prepare_config.sh:2
json_data=$(cat <<EOF
                  ^^^

SyntaxError: missing ) after argument list
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1033:15)
    at Module._compile (node:internal/modules/cjs/loader:1069:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Module._load (node:internal/modules/cjs/loader:827:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
    at node:internal/main/run_main_module:17:47

Node.js v18.1.0

Could you help fix that?

CodePudding user response:

A quick fix (docker-compose.yml related)

It appears your script is not run by /bin/bash, but by node (the "entrypoint" of your image).

To address your use case, you actually have two equivalent solutions:

  1. "reset the entrypoint" and directly use your command from the question
    → adding in your docker-compose.yml service definition:
myservice:
  entrypoint: []
  command: ["prepare_config.sh", "--", "npm", "run", "start-p"]
  1. set a nonempty entrypoint and command:
    → adding in your docker-compose.yml service definition, for instance:
myservice:
  entrypoint: ["prepare_config.sh", "--"]
  command: ["npm", "run", "start-p"]

Minor remark

As an aside:

  • solution 1. admits an equivalent docker run command:
    docker run --entrypoint="" image-name prepare_config.sh -- npm run start-p

  • but solution 2. does not have an equivalent docker run command, given the CLI option --entrypoint can only take one argument (the program binary), not a list…

A better fix (Dockerfile related)

However, even if your image is based on node:18-alpine3.14 which comes with a specific ENTRYPOINT that you want to override, it sounds better to directly modify your own Dockerfile.

Typically, you would write at the end of this file:

ENTRYPOINT ["prepare_config.sh", "--"]
CMD ["npm", "run", "start-p"]

Provided you already inserted a command to set the executable bit of your entrypoint, for instance:

RUN chmod a x prepare_config.sh

For more details on ENTRYPOINT and CMD, see e.g. this other StackOverflow answer:
What is the difference between CMD and ENTRYPOINT in a Dockerfile?.

CodePudding user response:

The entrypoint script in the node container tries to figure out if the command passed to it should be run by node or not.

It does that by checking if the first parameter is a system command or not. Your script is not a system command, so the entrypoint script decides that it should be run by node.

To convince the entrypoint script that your command shouldn't be run by node, you can explicitly say that you want it to be run by the shell like this

command: ["/bin/sh", "-c", "prepare_config.sh -- npm run start-p"]

/bin/sh is a system command, so the entrypoint script won't try to get node to run the command.

Also, be aware that Alpine images usually don't have bash installed, so you might have to change bash in #!/bin/bash in your script to sh or ash.

CodePudding user response:

Right now only this variant works fine

command: ["/bin/sh", "-c", "./prepare_config.sh && npm run start-p"]
  • Related