ADD/COPY files with sbt-native-packager's docker support

I’m using sbt-native-packager 1.0.0-M5 to create my docker image. I need to add a file that’s not a source file or in the resource folder. My docker commands are as follows:

dockerCommands := Seq(
  Cmd("FROM", "myrepo/myImage:1.0.0"),
  Cmd("COPY", "test.txt keys/"), // <-- The failing part
  Cmd("WORKDIR", "/opt/docker"),
  Cmd("RUN", "[\"chown\", \"-R\", \"daemon\", \".\"]"),
  Cmd("USER", "daemon"),
  ExecCmd("CMD", "echo", "Hello, World from Docker")
)

It fails with: msg="test.txt: no such file or directory"

  • how to reach another container from a dockerised nginx
  • Docker osx mounted folder is empty
  • StatusCode.UNAUTHENTICATED when running Vision API demo in Python/Flask running in Docker
  • Connect to Dockerized IIS remotely
  • OSX docker build error Command not found: -t
  • Source controlling (git) docker-compose.yml
  • So after digging around a bit it seems I need to have test.txt in target/docker/stage. Then it works. But how do I get it there automatically? The file is actually in the root folder of the project.

  • How does docker handle almost equal images?
  • Pulling of docker image from a registry fails
  • proxy_pass https in a Docker Container
  • Overriding `tcp.publish_port` breaks clustering when elasticsearch is in a container
  • Create new MongoDB instance based on existing data
  • How to run yum inside a docker container on a partially isolated host?
  • 4 Solutions collect form web for “ADD/COPY files with sbt-native-packager's docker support”

    I managed to get it to work by adding the file to mappings in Universal. So for you, you would need something like this:

    mappings in Universal += file("test.txt") -> "keys/test.txt"
    

    You won’t need the COPY command if you do this, by the way.

    Now, I’m not sure if this is going to add this mapping to other sbt-native-packager plugins. I hope a commenter can tell me whether or not this is true, but my intuition is that it will do so, which might be a dealbreaker for you. But any workaround is better than none, right? If you use Build.scala you could maybe use a VM argument to tell sbt whether or not to add this mapping…

    I was able to get this working using dockerPackageMappings:

    dockerPackageMappings in Docker += (baseDirectory.value / "docker" / "ssh_config") -> "ssh_config"
    
    dockerCommands := (dockerCommands.value match {
      case Seq(from@Cmd("FROM", _), rest@_*) =>
        Seq(
         from,
         Cmd("Add", "ssh_config", "/sbin/.ssh/config")
      ) ++ rest
    })
    

    I was able to add files this way:

    For example, to add a file located in src/main/resources/docker/some-file.ext

    dockerfile in docker := {
      val targetPath = "/usr/app"
    
      // map of (relativeName -> File) of all files in resources/docker dir, for convenience
      val dockerFiles = {
        val resources = (unmanagedResources in Runtime).value
        val dockerFilesDir = resources.find(_.getPath.endsWith("/docker")).get
        resources.filter(_.getPath.contains("/docker/")).map(r => dockerFilesDir.toURI.relativize(r.toURI).getPath -> r).toMap
      }
    
      new Dockerfile {
        from(s"$namespace/$baseImageName:$baseImageTag")
        ...
        add(dockerFiles("some-file.ext"), s"$targetPath/some-file.ext")
        ...
      }
    }
    

    You may place all additional files (which must be included in container image) into folder src/universal. Content of that folder will be automatically copied in /opt/app folder within your container image. You don’t need any additional configuration. See “Getting started with Universal Packaging” for additional info.

    Docker will be the best open platform for developers and sysadmins to build, ship, and run distributed applications.