0

I'm trying to use a startup script on a Google Compute Engine instance to either:

  1. If the docker container called rstudio is present but in stopped state, run docker start rstudio
  2. If the docker container is not present, run rstudio run --name=rstudio rocker/rstudio

From this SO I thought this could be achieved via docker top rstudio || docker run --name=rstudio rocker/rstudio but it seems to always error at the docker top rstudio part. In that case, I have tried piping docker top rstudio &>/dev/null but no effect.

I have a cloud-config that runs when the instance boots up.

My problem is that the script to run or start the container keeps registering as an error, and doesn't go on to the logic of pulling the image. I have tried putting it in a seperate bash script and directly via ExecStart - also putting "-" in front of the ExecStart command (which is supposed to ignore errors?) but this also seems to have no effect. This is where I have ended up:

#cloud-config

users:
- name: gcer
  uid: 2000

write_files:
- path: /home/gcer/docker-rstudio.sh
  permissions: 0755
  owner: root
  content: |
    #!/bin/bash

    echo "Docker RStudio launch script"
    if ! docker top rstudio &>/dev/null
    then
      echo "Pulling new rstudio"
      docker run -p 80:8787 \
                 -e ROOT=TRUE \
                 -e USER=%s -e PASSWORD=%s \
                  -v /home/gcer:/home/rstudio \
                  --name=rstudio \
                  %s
    else
      echo "Starting existing rstudio"
      docker start rstudio
    fi

- path: /etc/systemd/system/rstudio.service
  permissions: 0644
  owner: root
  content: |
    [Unit]
    Description=RStudio Server
    Requires=docker.service
    After=docker.service

    [Service]
    Restart=always
    Environment="HOME=/home/gcer"
    ExecStartPre=/usr/share/google/dockercfg_update.sh
    ExecStart=-/home/gcer/docker-rstudio.sh
    ExecStop=/usr/bin/docker stop rstudio

runcmd:
- systemctl daemon-reload
- systemctl start rstudio.service

Whatever I try, I end up with this error log when I run sudo journalctl -u rstudio.service

Feb 14 23:26:09 test-9 systemd[1]: Started RStudio Server.
Feb 14 23:26:09 test-9 docker[770]: Error response from daemon: No such container: rstudio
Feb 14 23:26:09 test-9 systemd[1]: rstudio.service: Control process exited, code=exited status=1
Feb 14 23:26:09 test-9 systemd[1]: rstudio.service: Unit entered failed state.
Feb 14 23:26:09 test-9 systemd[1]: rstudio.service: Failed with result 'exit-code'.
Feb 14 23:26:09 test-9 systemd[1]: rstudio.service: Service hold-off time over, scheduling restart.
Feb 14 23:26:09 test-9 systemd[1]: Stopped RStudio Server.
Feb 14 23:26:09 test-9 systemd[1]: Starting RStudio Server...
...
Feb 14 23:26:09 test-9 systemd[1]: Started RStudio Server.
Feb 14 23:26:09 test-9 docker[809]: Error response from daemon: No such container: rstudio
Feb 14 23:26:09 test-9 systemd[1]: rstudio.service: Control process exited, code=exited status=1
Feb 14 23:26:09 test-9 systemd[1]: rstudio.service: Unit entered failed state.
Feb 14 23:26:09 test-9 systemd[1]: rstudio.service: Failed with result 'exit-code'.
Feb 14 23:26:10 test-9 systemd[1]: rstudio.service: Service hold-off time over, scheduling restart.
Feb 14 23:26:10 test-9 systemd[1]: Stopped RStudio Server.
Feb 14 23:26:10 test-9 systemd[1]: rstudio.service: Start request repeated too quickly.
Feb 14 23:26:10 test-9 systemd[1]: Failed to start RStudio Server.
Feb 14 23:26:10 test-9 systemd[1]: rstudio.service: Unit entered failed state.
Feb 14 23:26:10 test-9 systemd[1]: rstudio.service: Failed with result 'exit-code'.

Can anyone help me get this working?

MarkeD
  • 2,500
  • 2
  • 21
  • 35

1 Answers1

0

I would delete the container when you stop it. Then your startup script reduces to making extra sure the container is deleted, and unconditionally docker running it anew.

This would make the entire contents of the script be:

#!/bin/sh
docker stop rstudio
docker rm rstudio
docker run -p 80:8787 \
   --name=rstudio \
   ... \
   rstudio run --name=rstudio rocker/rstudio

Without the set -e option, even if the earlier commands fail (because the container doesn't exist) the script will still go on to the docker run command. This avoids any testing of trying to figure out whether a container is there or not and always leaves you in a consistent state.

Similarly, to clean up a little better, I'd change the systemd unit file to delete the container after it stops

ExecStop=/usr/bin/docker stop rstudio
ExecStopPost=/usr/bin/docker rm rstudio

(Your setup has three possible states: the container is running; the container exists but is stopped; and the container doesn't exist. My setup removes the "exists but is stopped" state, which doesn't have a whole lot of value, especially since you use a docker run -v option to store data outside of container space.)

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • Heh, thanks for reply but that’s exactly how it’s setup now - I’m looking to replace it by restarting an existing container as users install libraries within the container and I’ve been advised to not link those installations to the base VM via the volume tag. I was hoping getting the container to restart would be a compromise – MarkeD Feb 15 '19 at 07:47
  • That sounds like a setup where it will be impossible to take security updates or otherwise change the underlying image at all without losing users' data, and that's going to be a big problem. (You _have_ to delete the container sometimes.) – David Maze Feb 15 '19 at 10:29
  • Hmm, I agree and follow that principle for my own stuff, but was giving users the option, but perhaps I can find a different approach, like saving a copy of the container. Still would be interested why the script above isn't working through, for my own education :) – MarkeD Feb 15 '19 at 16:07