I have an old rpm package that is incompatible with RHEL 8 operating system. I made it into a docker image, hoping to run it in a docker way. But I failed. I don’t know where the problem lies.
Dockerfile
# Dockerfile
FROM centos:7
COPY mediaserver-1.0.1-12.dev7.x86_64.rpm /opt/
COPY start_up.sh /opt/
RUN yum install -y gnutls && yum install -y /opt/mediaserver-1.0.1-12.dev7.x86_64.rpm
&& rm -f /opt/mediaserver-1.0.1-12.dev7.x86_64.rpm
&& yum clean all
&& rm -rf /var/cache/yum
&& chmod +x /opt/start_up.sh
WORKDIR /opt/mediaserver
EXPOSE 6001
EXPOSE 17612
ENTRYPOINT ["/bin/bash","-c"]
CMD sh /opt/start_up.sh
start_up.sh
#!/bin/bash
/etc/init.d/"$program_name" start &
appid=$!
sleep 5
ps aux | grep -q "$program_name"
if [ $? -ne 0 ]; then
echo "media app failed to start"
exit 1
fi
echo $appid > /opt/mediaserver/app.pid
exit 0
I use docker run -it
, I can enter the container normally, but the service does not start. I can start it manually.
I use docker run -it, I can enter the container normally, but the service does not start. I can start it manually.
root 30512 1 0 23:52 ? 00:00:00 /opt/mediaserver/bin/SystemShell -r mediaserver:/opt/mediaserver/bin/mediaserve root 30513 30512 3 23:52 ? 00:00:00 /opt/mediaserver/bin/mediaserver -s mediaserver -m
2
Answers
Your
start_up.sh
requires a variable name$program_name
, however, you have not defined it anywhere. That’s why usingCMD sh /opt/start_up.sh
results Docker container stops atsh
shell and wait for next instructions.To fix this, you can either
$program_name
with your application name, for example, if mediaserver start up script ismediaserver
then replace$program_name
withmediaserver
start_up.sh
to accept an input, then update CMD to something likeCMD sh /opt/start_up.sh mediaserver
(assumed that the program name ismediaserver
A Docker container is a wrapper around a single process. The best approach here is to not use any sort of init script, wrapper, or tricks to "keep the container alive"; instead, just run the process in the foreground as the main container
CMD
.The fundamental model of a Docker container is that it runs the single command that comes from combining
ENTRYPOINT
andCMD
. When that command exits, the container exits too.If you read through your script, you run an
init.d
script as a background process, sleep for 5 seconds, maybe write a pid file, and either wayexit
. This means that the container will always exit almost immediately; the background process won’t keep running because the main container process has exited.If you’re using this model, you need to do something to cause the main container process to not exit. The most common workaround is to
sleep infinity
. Note that this isn’t especially connected to the actual process in the container, though: if thatmediaserver
process exits for whatever reason, since thesleep
command is still running, the container will still stay "alive" as well.Finally: there’s a mechanical problem in the interaction between
ENTRYPOINT
andCMD
as you’ve shown it. These work as:sh -c
; thenENTRYPOINT
andCMD
into a single word list.Applying those rules, you get the equivalent of
which gets parsed as
/bin/bash -c
interpret and run a command,/bin/sh
the command to run,-c 'sh /opt/start_up.sh'
positional parameters to that command starting with$0
. That is, this only runs a shell and not your startup script.You never need to write
["sh", "-c", ...]
in a Dockerfile; the shell form without JSON-array syntax is simpler if you need that. You also do not need to split the command into its "command" and "arguments", just a singleCMD
line is usually fine.In short: if you delete the
ENTRYPOINT
line without replacement, your script will actually run.