18
votes

I'm running a single Docker container on Elastic Beanstalk using its Single Container Docker Configuration, and trying to send the application stdout to CloudWatch using the awslogs logging driver.

EB looks for a Dockerrun.aws.json file for the configuration of the container, but as far as I can see doesn't have an option to use awslogs as the container's logging driver (or add any other flags to the docker run command for that matter).

I've tried hacking into the docker run command using the answer provided here, by adding a file .ebextensions/01-commands.config with content:

commands:
  add_awslogs:
    command: 'sudo sed -i "s/docker run -d/docker run --log-driver=awslogs --log-opt awslogs-region=eu-west-2 --log-opt awslogs-group=dockerContainerLogs -d/" /opt/elasticbeanstalk/hooks/appdeploy/enact/00run.sh'

This works, in the sense that it modifies the run script, and logs show up in CloudWatch.

But the EB application dies. The container is up, but does not respond to requests.

I find the following error in the container logs:

"logs" command is supported only for "json-file" and "journald" logging drivers (got: awslogs)

I find answers to similar questions relating to ECS (not EB) suggesting to append ECS_AVAILABLE_LOGGING_DRIVERS with awslogs. But I don't find this configuration setting in EB.

Any thoughts?

2

2 Answers

20
votes

I'm posting here the answer I received from AWS support:

As Elastic Beanstalk Single Container environment will save the stdout and stderr on /var/log/eb-docker/containers/eb-current-app/ by default, and as the new solution stack allows you the option to stream log to cloudwatch, automating the configuration of the AWSLogs agent on the instances, what I recommend to do is to add an ebextension to add the stdout and stderr logs files to the cloudwatch configuration and use the already configured agent to stream those files to cloudwatch logs. instead of touching the pre-hooks , which is nor supported by AWS as hooks may change from solution stack version to another.

Regarding the error you are seeing "logs" command is supported only for "json-file" and "journald" logging drivers (got: awslogs)" this error is from how docker works, when it is configured to send logs to other driver beside json-file or journald it will not be able to display logs locally as it does not have a local copy of them.

### BEGIN .ebextensions/logs.config
option_settings:
  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: StreamLogs
    value: true
  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: DeleteOnTerminate
    value: false
  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: RetentionInDays
    value: 7

files:
  "/etc/awslogs/config/stdout.conf":
    mode: "000755"
    owner: root
    group: root
    content: |
      [docker-stdout]
      log_group_name=/aws/elasticbeanstalk/environment_name/docker-stdout
      log_stream_name={instance_id}
      file=/var/log/eb-docker/containers/eb-current-app/*-stdouterr.log

commands:
  "00_restart_awslogs":
    command: service awslogs restart

### END .ebextensions/logs.config
7
votes

I was able to expand on the previous answer for a multi container elastic beanstalk environment as well as inject the environment name. I did have to grant the correct permission in the ec2 role to be able to create the log group. You can see if it is working by looking in:

/var/log/awslogs.log

this goes in .ebextensions/logs.config

option_settings:
  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: StreamLogs
    value: true
  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: DeleteOnTerminate
    value: false
  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: RetentionInDays
    value: 14

files:
  "/etc/awslogs/config/stdout.conf":
    mode: "000755"
    owner: root
    group: root
    content: |
      [/var/log/containers/docker-stdout]
      log_group_name=/aws/elasticbeanstalk/`{ "Ref" : "AWSEBEnvironmentName" }`/docker-stdout.log
      log_stream_name={instance_id}
      file=/var/log/containers/*-stdouterr.log

commands:
  "00_restart_awslogs":
    command: service awslogs restart