Introduction

AWS elastic beanstalk has been able to run docker based applications. Containers can either be pulled from a docker repository, after being built elsewhere, or based on an archive containing a Dockerfile and its associated files. The docker image is then build by the docker daemon on the elastic beanstalk service.

Using sbt native packager, one can deploy scala applications from sbt to a docker image. If using a docker repository to deploy to elastic beanstalk, one can simply use docker:publish to build and publish the image and then instruct elastic beanstalk to grab the image. You can also deploy the image by running docker:stage, creating a zip archive containing the created Dockerfile, files, a Dockerrun.aws.json and any other required extension configurations.

The issue

The problem is native packager leverages a bash run script that’s added to the docker image. There is a known issue that files can loose their runnable permission in a zip archive (here here and here) When creating the zip bundle, the shell script will lose its runnable permission and the image will fail in elastic beanstalk.

The solution

We want to ensure that the run script has execute permissions before we attempt to run it. We want to add the following to our Dockerfile before the ENTRYPOINT and CMD is run

RUN chmod +x runscript.sh

To do this we will modify the dockerfile created by native packager by flatMapping over the dockerCommands in build.sbt and adding the chmod before the ENTRYPOINT as follows:

dockerCommands <<= (dockerCommands, dockerEntrypoint) map { (com, ent) =>
  com.flatMap {
    case e : ExecCmd if e.cmd == "ENTRYPOINT" =>
      val chmodCommand = Seq("chmod", "+x") ++ ent
      Seq(ExecCmd("RUN", chmodCommand: _*), e)
    case e => Seq(e)
  }
}

Breaking that down, we flatMap over the existing dockerCommands and when we hit the ENTRYPOINT command, we insert another command before it that runs chmod on the dockerEntrypoint. Note that we don’t hard code the run script itself, we simply depend on whatever it is set as.