skip to Main Content

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


  1. Your start_up.sh requires a variable name $program_name, however, you have not defined it anywhere. That’s why using CMD sh /opt/start_up.sh results Docker container stops at sh shell and wait for next instructions.

    To fix this, you can either

    • Hard code your init script by updating $program_name with your application name, for example, if mediaserver start up script is mediaserver then replace $program_name with mediaserver
    • Or update your start_up.sh to accept an input, then update CMD to something like CMD sh /opt/start_up.sh mediaserver (assumed that the program name is mediaserver
    Login or Signup to reply.
  2. 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.

    # (no ENTRYPOINT)
    CMD /opt/mediaserver/bin/mediaserver -s mediaserver -m
    

    The fundamental model of a Docker container is that it runs the single command that comes from combining ENTRYPOINT and CMD. 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 way exit. 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 that mediaserver process exits for whatever reason, since the sleep command is still running, the container will still stay "alive" as well.


    Finally: there’s a mechanical problem in the interaction between ENTRYPOINT and CMD as you’ve shown it. These work as:

    1. If either or both of these is a bare string, wrap them in sh -c; then
    2. Concatenate the lists of words in ENTRYPOINT and CMD into a single word list.

    Applying those rules, you get the equivalent of

    ENTRYPOINT+CMD ["/bin/bash", "-c", "/bin/sh", "-c", "sh /opt/start_up.sh"]
    #               ^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^
    #                   ENTRYPOINT     added by Docker           CMD
    

    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 single CMD line is usually fine.

    In short: if you delete the ENTRYPOINT line without replacement, your script will actually run.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search