7

I have a Docker container that runs great on my local development machine. I would like to move this to AWS Elastic Beanstalk, but I am running into a small bit of trouble.

I am trying to mount an S3 bucket to my container by using s3fs. I have the Dockerfile:

FROM tomcat:7.0
MAINTAINER me@example.com

RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential libfuse-dev libcurl4-openssl-dev libxml++2.6-dev libssl-dev mime-support automake libtool wget tar 

# Add the java source
ADD . /path/to/tomcat/webapps/
ADD run_docker.sh /root/run_docker.sh
WORKDIR $CATALINA_HOME

EXPOSE 8080

CMD ["/root/run_docker.sh"]

And I install s3fs, mount an S3 bucket, and run the Tomcat server after the image has been created, by running run_docker.sh:

#!/bin/bash
#run_docker.sh

wget https://github.com/s3fs-fuse/s3fs-fuse/archive/master.zip -O /usr/src/master.zip;
cd /usr/src/;
unzip /usr/src/master.zip;
cd /usr/src/s3fs-fuse-master;
autoreconf --install;
CPPFLAGS=-I/usr/include/libxml2/ /usr/src/s3fs-fuse-master/configure;
make;
make install;
cd $CATALINA_HOME;

mkdir /opt/s3-files;
s3fs my-bucket /opt/s3-files;
catalina.sh run

When I build and run this Docker container using the command:

docker run --cap-add mknod --cap-add sys_admin --device=/dev/fuse -p 80:8080 -d username/mycontainer:latest

it works well. Yet, when I remove the --cap-add mknod --cap-add sys_admin --device=/dev/fuse, then s3fs fails to mount my S3 bucket.

Now, I would like to run this on AWS Elastic Beanstalk, and when I deploy the container (and run run_docker.sh), all the steps execute fine, except the step s3fs my-bucket /opt/s3-files in run_docker.sh fails to mount the bucket.

Presumably, this is because whatever Elastic Beanstalk does to run a Docker container, it doesn't add any additional flags like, --cap-add mknod --cap-add sys_admin --device=/dev/fuse.

My Dockerrun.aws.json file looks like:

{
  "AWSEBDockerrunVersion": "1",
  "Image": {
    "Name": "tomcat:7.0"
  },
  "Ports": [
    {
      "ContainerPort": "8080"
    }
  ]
}

Is it possible to add additional docker run flags to an AWS EB Docker deployment? An alternative option is to find another way to mount an S3 bucket, but I suspect I'd run into similar permission errors regardless. Has anyone seen any way to accomplish this???

UPDATE:

For people trying to use @Egor's answer below, it works when the EB configuration is set to use v1.4.0 running Docker 1.6.0. Anything past the v1.4.0 version fails. So to make it work, build your environment as normal (which should give you a failed build), then rebuild it with a v1.4.0 running Docker 1.6.0 configuration. That should do it!

Brett
  • 11,637
  • 34
  • 127
  • 213
  • How can you rebuild an environment using the '1.4.0 running Docker 1.6.0' configuration? The EB console does not seem to offer this option, neither does the documentation. – zerodot Jul 14 '15 at 09:13

4 Answers4

9

If you are using the latest version of aws docker stack (docker 1.7.1 for example), you'll need to slightly modify the above answer. Try this:

commands:
    00001_add_privileged:
        cwd: /tmp
        command: 'sed -i "s/docker run -d/docker run --privileged -d/" /opt/elasticbeanstalk/hooks/appdeploy/enact/00run.sh'

Notice the change of location && name of the run script

David Saetrum
  • 91
  • 1
  • 2
  • I've been wondering how to do this for a LONG time, fantastic. In my case I was trying to pass args to a public docker image repo, so I used `command: 'sed -i "s/\$EB_CONFIG_DOCKER_IMAGE_STAGING/\$EB_CONFIG_DOCKER_IMAGE_STAGING -gzip -enable-url-source/" /opt/elasticbeanstalk/hooks/appdeploy/enact/00run.sh'` – Kyle Chadha Dec 01 '15 at 16:13
  • Awesome. Glad it could help. – David Saetrum Dec 02 '15 at 18:56
4

Add file .ebextensions/01-commands.config

container_commands:
    00001-docker-privileged: command: 'sed -i "s/docker run -d/docker run --privileged -d/" /opt/elasticbeanstalk/hooks/appdeploy/pre/04run.sh'

I am also using s3fs

Egor Yurtaev
  • 127
  • 3
  • Interesting. What is `04run.sh` here? Is that specific to your environment/setup? Or is the docker `run` step simply the 4th step that EB does? – Brett Feb 02 '15 at 13:48
  • https://gist.github.com/yurtaev/1e8d639cb03bbb95e71a#file-04run-sh is a specific file for EB – Egor Yurtaev Feb 02 '15 at 15:05
  • This is - *unfortunately* - not working for me. I see that `04run.sh` is modified and includes the `--privileged` flag, but the logs state: `fuse: failed to open /dev/fuse: Operation not permitted`. Any ideas? – Brett Feb 03 '15 at 17:06
  • 1
    Minor update. I ssh'ed into the host instance on EB, stopped the Docker container, removed it, then reran it using the `--privileged` flag; and that worked. So it looks like `sed` command isn't being executed prior to `04run.sh` being run. – Brett Feb 03 '15 at 19:50
  • I am having the same issue as @Brett where I get the Operation not permitted. Is there any new information on this? – Mike Feb 26 '15 at 17:07
2

Thanks elijahchancey for answer it was much helpful. I would just like to add small comment:

Elasticbeanstalk is now using ECS tasks to deploy and manage application cluster. There is very important paragraph in Multicontainer Docker Configuration docs (which I originally missed).

The following examples show a subset of parameters that are commonly used. More optional parameters are available. For more information on the task definition format and a full list of task definition parameters, see Amazon ECS Task Definitions in the Amazon ECS Developer Guide.

So the document is not complete reference but it just shows typical entries and you are supposed to find more elsewhere. This has quite major impact because now (2018) you are able to specify more options and you don't need to hack ebextensions any more. Only thing you need to do is to use task parameter in containerDefinitions of your multi docker Dockerrun.aws.json.

This is not mentioned in single docker containers but one can try and verify...

Example of multi docker Dockerrun.aws.json with extra cap:

{
  "AWSEBDockerrunVersion": 2,
  "containerDefinitions": [
    {
      "name": "service1",
      "image": "myapp/service1:latest",
      "essential": true,
      "memoryReservation": 128,
      "portMappings": [
        {
          "hostPort": 8080,
          "containerPort": 8080
        }
      ],
      "linuxParameters": {
        "capabilities": {
          "add": [
            "SYS_PTRACE"
          ]
        }
      }
    }
  ]
}
anebril
  • 276
  • 2
  • 12
1

You can now add capabilities using the task definition. Here are the docs: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html

This is specifically what you would add to your task definition:

"linuxParameters": {
    "capabilities": {
      "add": [
        "SYS_PTRACE"
      ]
    }
  },