Docker Image Entry Point Script Not Found

2019-06-07 06:12发布

问题:

I have a Dockerfile like:

FROM frolvlad/alpine-oraclejdk8:slim
ADD build/libs/zuul*.jar /app.jar
ADD src/main/script/startup.sh /startup.sh
EXPOSE 8080 8999
ENTRYPOINT ["/startup.sh"]

startup.sh looks like:

#!/bin/sh
set -e

if [ $# -eq 0 ]
then
    echo "Environment value required"
    exit 1
fi

java -jar -Xms400m -Xmx400m -Dlog4j.configurationFile=log4j2-qa2.xml -Djava.security.egd=file:/dev/./urandom -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8999 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.rmi.port=8999 app.jar

But when I run it with docker run, I got docker: Error response from daemon: Container command '/startup.sh' not found or does not exist... The shell script has execute permission.

I used the same way to run my other apps and they're all working fine. I wrote the files in Mac and tried to run the container in a Linux machine.

回答1:

It turns out to be the ^M DOS-style line ending character that caused the issue. But since I'm editing in Mac and I checked several times with vim, I'm pretty sure the starting script in my local machine doesn't have that char. But when opened with vim inside the container, I can see ^M everywhere. So somehow that char gets added to startup.sh when copied into the image, which is weird. That prevents the script from being invoked.

The solution is to add dos2unix filename before the ENTRYPOINT in Dockerfile. But make sure that your base image has that utility.



回答2:

The shell script has execute permission.

Are you sure though? (I mean within the container, onced ADDed)
To be sure, I would use the Dockerfile:

EXPOSE 8080 8999
COPY src/main/script/startup.sh /startup.sh
RUN chmod 755 /startup.sh
WORKDIR /
ENTRYPOINT ["/startup.sh"]


回答3:

A container exits when its main process exits. So check that /startup.sh is not ending.

Particularly check that this java

java -jar -Xms400m -Xmx400m -Dlog4j.configurationFile=log4j2-qa2.xml \
  -Djava.security.egd=file:/dev/./urandom \
  -Dcom.sun.management.jmxremote \
  -Dcom.sun.management.jmxremote.port=8999 \
  -Dcom.sun.management.jmxremote.local.only=false \
  -Dcom.sun.management.jmxremote.rmi.port=8999 \
  app.jar


回答4:

I think the trouble here is when you specify path like /app.jar, it is really difficult to make out where the current working directory actually is.

It can be any where and I suspect Docker must have accidentally copy your start.sh to a place whatever at that point ./ is.

You might want to ssh into the container and do a find to search and see where startup.sh is sitting.

  1. docker ps -a - Find docker container ID
  2. docker -i -t [CONTAINER_ID] /bin/bash - SSH inside
  3. find . -name "startup.sh" - Look for file.

If you intend to copy the files through using ./ (current working directory), I think it would be better to specify where current is. And you can do this using the WORKDIR keyword.

Example: WORKDIR /path/to/workdir

The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile. If the WORKDIR doesn’t exist, it will be created even if it’s not used in any subsequent Dockerfile instruction.

That way docker will not get confused.

See: https://docs.docker.com/engine/reference/builder/#/workdir



标签: docker