Docker produces incorrect ENTRYPOINT command - docker

I'm trying to build docker image for my application but I can't run container based on this image because of failing ENTRYPOINT execution:
User.Name#pc-name MINGW64 ~
$ docker run some-repository.com/application-name:latest
/bin/sh: line 0: [: missing `]'
There is my Dockerfile:
FROM some-repository.com/openjdk:11.0.5-jre-slim as build
FROM some-repository.com/rhel7-atomic
COPY --from=build /usr/local/openjdk-11 jx/
LABEL Team="some-team"
LABEL AppVersion=1111
RUN mkdir -p id
COPY application-name-1.6.17-SNAPSHOT.jar id
EXPOSE 26000
ENTRYPOINT [ "sh", "-c", "exec echo hello \$JAVA_OPTS \
world"]
There is result of docker inspect:
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"ENTRYPOINT [\"/bin/sh\" \"-c\" \"[ \\\"sh\\\", \\\"-c\\\", \\\"exec echo hello \\\\$JAVA_OPTS world\\\"]\"]"
],
"ArgsEscaped": true,
"Entrypoint": [
"/bin/sh",
"-c",
"[ \"sh\", \"-c\", \"exec echo hello \\$JAVA_OPTS world\"]"
]
Looks like ENTRYPOINT command was interpolated incorrectly and [ character was added to the command.
Why this problem appears and how can I fix it?

Remove the escape in front of the $, it's an invalid escape in json and when the string doesn't parse as json it gets parsed as a string passed to a shell.
ENTRYPOINT [ "sh", "-c", "exec echo hello $JAVA_OPTS \
world"]
If you wanted echo to print a $, rather than having sh expand the variable, then you'd need a double escape to escape the escape character, so that json would pass a single \ to the command being run:
ENTRYPOINT [ "sh", "-c", "exec echo hello \\$JAVA_OPTS \
world"]

Related

Dockerfile - CMD with nohup

How can I put the following into Dockerfile? I'm rebuilding a image and have modified few things.
Upon inspecting the original image, I see that it has CMD in a weird format.
"Cmd": [
"/bin/sh",
"-c",
"#(nop) CMD [\"supervisord\" \"-c\" \"/etc/supervisor.conf\"]"
],
The Entrypoint script executes this as its argument. But I'm unsure how to add this in the new Dockerfile.
I'm not sure if I can have 2 CMD and not sure how to add the nohup in a Dockerfile
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["/bin/sh", "-c", "#(nop)"]
CMD ["supervisord","-c", "/etc/supervisor.conf"]
Here is the entrypoint.sh
#!/bin/bash
set -eo pipefail
# if command starts with an option, prepend supervisord
if [ "${1:0:1}" = '-' ]; then
set -- supervisord "$#"
fi
# Add local user;
# Either use the MARADNS_USER_ID if passed in at runtime or fallback.
USER_ID=${MARADNS_USER_ID:-9001}
echo "Starting with UID : $USER_ID"
usermod -u $USER_ID maradns
# update permissions
chown -R maradns.maradns /etc/maradns
chown -R maradns.maradns /var/cache/deadwood
# replace the UID and GID of the maradns user
MARADNS_UID=`id -u maradns`
MARADNS_GID=`id -g maradns`
cp /etc/mararc.custom /etc/mararc
sed -i -r "s/(maradns_uid\s*=\s*)([0-9]+)(.*)/\1${MARADNS_UID}\3/" /etc/mararc
sed -i -r "s/(maradns_gid\s*=\s*)([0-9]+)(.*)/\1${MARADNS_GID}\3/" /etc/mararc
# bind maradns on container host
MARADNS_ADDRESS=`ifconfig eth0 | grep 'inet addr:' | cut -d ' ' -f12 | cut -d ':' -f2`
sed -i -r "s/(ipv4_bind_addresses\s*=\s*)(.*)(.*)/\1\"${MARADNS_ADDRESS}\"\3/" /etc/mararc
# copy filebeat configuration
cp /etc/filebeat/filebeat.yml.custom /etc/filebeat/filebeat.yml
# run command
exec "$#"

Use build-arg from docker to create json file

I have a docker build command which I'm running in Jenkins execute shell
docker build -f ./fastlane.dockerfile \
-t fastlane-test \
--build-arg PLAY_STORE_CREDENTIALS=$(cat PLAY_STORE_CREDENTIALS) \
.
PLAY_STORE_CREDENTIALS is a JSON file saved in Jenkins using managed files. And, then, inside my Dockerfile, I have
ARG PLAY_STORE_CREDENTIALS
ENV PLAY_STORE_CREDENTIALS=$PLAY_STORE_CREDENTIALS
WORKDIR /app/packages/web/android/fastlane/PlayStoreCredentials
RUN touch play-store-credentials.json
RUN echo $PLAY_STORE_CREDENTIALS >> ./play-store-credentials.json
RUN cat play-store-credentials.json
cat logs out a empty line or nothing at all.
Content of PLAY_STORE_CREDENTIALS:
{
"type": "...",
"project_id": "...",
"private_key_id": "...",
"private_key": "...",
"client_email": "...",
"client_id": "...",
"auth_uri": "...",
"token_uri": "...",
"auth_provider_x509_cert_url": "...",
"client_x509_cert_url": "..."
}
Any idea where the problem is?
Is there actually a file named PLAY_STORE_CREDENTIALS? If it is, and if it's a standard JSON file, I would expect your given command line to fail; if the file contains any whitespace (which is typical for JSON files), that command should result in an error like...
"docker build" requires exactly 1 argument.
For example, if I have in PLAY_STORE_CREDENTIALS the sample content from your question, we see:
$ docker build -t fastlane-test --build-arg PLAY_STORE_CREDENTIALS=$(cat PLAY_STORE_CREDENTIALS) .
"docker build" requires exactly 1 argument.
See 'docker build --help'.
Usage: docker build [OPTIONS] PATH | URL | -
...because you are not properly quoting your arguments. If you adopt #β.εηοιτ.βε's suggestion and quote the cat command, it appears to build as expected:
$ docker build -t fastlane-test --build-arg PLAY_STORE_CREDENTIALS="$(cat PLAY_STORE_CREDENTIALS)" .
[...]
Step 7/7 : RUN cat play-store-credentials.json
---> Running in 29f95ee4da19
{ "type": "...", "project_id": "...", "private_key_id": "...", "private_key": "...", "client_email": "...", "client_id": "...", "auth_uri": "...", "token_uri": "...", "auth_provider_x509_cert_url": "...", "client_x509_cert_url": "..." }
Removing intermediate container 29f95ee4da19
---> b0fb95a9d894
Successfully built b0fb95a9d894
Successfully tagged fastlane-test:latest
You'll note that the resulting file does not preserve line endings; that's because you're not quoting the variable $PLAY_STORE_CREDENTIALS in your echo statement. You should write that as:
RUN echo "$PLAY_STORE_CREDENTIALS" >> ./play-store-credentials.json
Lastly, it's not clear why you're transferring this data using environment variables, rather than just using the COPY command:
COPY PLAY_STORE_CREDENTIALS ./play-store-credentials.json
In the above examples, I'm testing things using the following Dockerfile:
FROM docker.io/alpine:latest
ARG PLAY_STORE_CREDENTIALS
ENV PLAY_STORE_CREDENTIALS=$PLAY_STORE_CREDENTIALS
WORKDIR /app/packages/web/android/fastlane/PlayStoreCredentials
RUN touch play-store-credentials.json
RUN echo $PLAY_STORE_CREDENTIALS >> ./play-store-credentials.json
RUN cat play-store-credentials.json
Update
Here's an example using the COPY command, where the value of the PLAY_STORE_CREDENTIALS build argument is a filename:
FROM docker.io/alpine:latest
ARG PLAY_STORE_CREDENTIALS
WORKDIR /app/packages/web/android/fastlane/PlayStoreCredentials
COPY ${PLAY_STORE_CREDENTIALS} play-store-credentials.json
RUN cat play-store-credentials.json
If I have credentials in a file named creds.json, this builds successfully like this:
docker build -t fastlane-test --build-arg PLAY_STORE_CREDENTIALS=creds.json .

Run multiple command after entrypoint with docker-compose

I have been looking to the matrix of interaction of CMD and ENTRYPOINT and I can't found my way to have container running an entrypoint THEN a cmd with multiple commands
version: '3.8'
services:
test:
image: debian:buster-slim
entrypoint: [ "/entrypoint.sh" ]
volumes:
- ./entrypoint.sh:/entrypoint.sh
command: [ "echo" ,"toto","&&","echo","tutu" ]
where entrypoint.sh is a file containing :
#!/bin/bash
set -e
set -x
echo tata
exec "$#"
"should" print
tata
toto
tutu
but it's printing
tata
toto && echo tutu
I found a solution by replacing [ "echo" ,"toto","&&","echo","tutu" ] by "bash -c 'echo toto && echo tutu'" and then it work.
but I don't get why the first method do not work since the documentation say it will do :
exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd
The problem is generated by the exec command, which synopsis is:
exec [command [argument...]]
so it will only accept one command with multiple arguments.
Solution:
The solution is the one that you pointed out, by using sh -c '':
services:
test:
image: debian:buster-slim
entrypoint: [ "/entrypoint.sh" ]
volumes:
- ./entrypoint.sh:/entrypoint.sh
command: ["sh", "-c", "echo toto && echo tutu"]
because the final result will satisfy the exec command with one command and multiple arguments
On docker side, the official documentation explains the ENTRYPOINT vs CMD very well with this table:
docker table
source
If you combine CMD and ENTRYPOINT in the array context the result would be /entrypoint.sh "echo" "toto" "&&" "echo" "tutu" because each parameter of the CMD will be a parameter for the ENTRYPOINT
Here's the output of the example above executed directly in the terminal:
# ./entrypoint.sh "echo" "toto" "&&" "echo" "tutu"
+ echo tata
tata
+ exec echo toto '&&' echo tutu
toto && echo tutu
And this is the result of the docker-compose up
# docker-compose up
test_1 | + echo tata
test_1 | tata
test_1 | + exec echo toto '&&' echo tutu
test_1 | toto && echo tutu
root_test_1 exited with code 0
As you can see each parameter is passed in the array form so the '&&' is parsed as a string (note the single quotes).
Note:
The result you expected is this one:
# ./entrypoint.sh echo toto && echo tutu
+ echo tata
tata
+ exec echo toto
toto
tutu
In this scenario as you see the only parameter passed to the exec is the first echo toto.
echo tutu is executed in bash terminal after ./entrypoint.sh script exits.
Obviously if this would be parsed by docker as a separate command it will never be executed because the ENTRYPOINT will exit before the echo tutu command.

How do I get a Command to run from a Dockerfile.aws.json on Elastic Beanstalk?

I have a Dockerfile and a Dockerfile.aws.json:
{
"AWSEBDockerrunVersion": "1",
"Ports": [{
"ContainerPort": "5000",
"HostPort": "5000"
}],
"Volumes": [{
"HostDirectory": "/tmp/download/models",
"ContainerDirectory": "/models"
}],
"Logging": "/var/log/nginx",
"Command": "mkdir -p /tmp && axel https://example.com/models.zip -o /tmp/models.zip"
}
But when I deploy, it doesn't run the Command that I specified. What am I doing wrong?
If you have ENTRYPOINT in your Dockerfile, than the Command gets appended as its arguments:
Specify a command to execute in the container. If you specify an Entrypoint, then Command is added as an argument to Entrypoint. For more information, see CMD in the Docker documentation.
Thus your Command mkdir -p /tmp ... will be used as an argument to python3 -m flask run --host=0.0.0.0, resulting in error. This could explain why you experience issue.
I tried to recreate the issue initially using your Command structure but had some problems. What worked was using Command in the following way:
"Command": "/bin/bash -c \"mkdir -p /tmp && axel https://example.com/models.zip -o /tmp/models.zip\""
My Dockerfile did not have Entrypoint. Thus to run your python you could maybe do the following (assuming everything else is correct):
"Command": "/bin/bash -c \"mkdir -p /tmp && axel https://example.com/models.zip -o /tmp/models.zip && python3 -m flask run --host=0.0.0.0\""
Do you have the Dockerfile content?
It most likely they your ENTRYPOINT script does not receive parameters, or it is ignoring it.
What you can do is something similar to this.
You have an entrypoint script that receive the command passed in aws.json as parameter, execute it and then call your real python command.
Or you can replace your ENTRYPOINT by something similar to this:
ENTRYPOINT ["/bin/bash"]
and your default command will be:
CMD ["python3 ..."]
This way when running locally you only run the python3 command.
When running in aws, you can change your Command and append the python to the end, as mentioned by Marcin. Both cases works

"/bin/sh: [/bin/sh,: not found" response when spining up kilna/liquibase-postgres

when spinning up docker image [kilna/liquibase-postgres], we are getting:
"/bin/sh: [/bin/sh,: not found"
As a response in the container log and the container is exiting abruptly.
Additional Note: We are using macOS Catalina and default bash is zsh.
Any pointers appreciated. Thank you
The command given in the Dockerfile is incorrect.
"Cmd": [
"/bin/sh",
"-c",
"['/bin/sh', '-i']"
],
It has nested /bin/sh. Argument for the flag -c should be a single string. It can not be an array.
So, it gives docker run kilna /bin/sh: [/bin/sh,: not found error.
Change the CMD as CMD ["/bin/sh", "-c", "/bin/sh -i"], build and run.
$ docker run -it kilna
/ #

Resources