curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk install grails
grails create-app dinte2018
cd dinte2018
# inside grails-app/conf/application.yml
# 1) remove environments.production.dataSource.properties
# 2) update environments.production.dataSource.url to use in-memory database
# 3) set environments.production.dataSource.dbCreate to update
# before creating the WAR
grails war
AWS Elastic Beanstalk is an easy-to-use service for deploying and scaling web applications and services developed with Java
plugins {
id "fi.evident.beanstalk" version "0.2.0"
}
// ...
// version needs to be unique during deployment but plugin supports snapshots
version = "0.1-SNAPSHOT"
// ...
beanstalk {
s3Endpoint = "s3-eu-west-1.amazonaws.com"
beanstalkEndpoint = "elasticbeanstalk.eu-west-1.amazonaws.com"
deployments {
gr8war {
file = tasks.war
application = 'dinte2018'
environment = 'Dinte2018-env'
}
}
}
./gradlew deployGr8war
pip install awscli --upgrade --user
aws configure
# AWS Access Key ID [****************C7YQ]: AAAAAAA
# AWS Secret Access Key [****************ci+o]: BBBBBBBBBBBB
# Default region name [eu-west-1]: eu-west-1
# Default output format [None]:
./gradlew deployGr8war
// uncomment/remove "war" plugin
// apply plugin:"war"
// ...
deployments {
gr8jar {
file = tasks.jar
application = 'dinte2018'
environment = 'gr8jar'
}
}
// run "assemble" before deployment to create fat jar
tasks.withType(fi.evident.gradle.beanstalk.DeployTask) {
dependsOn assemble
}
# add following into grails-app/conf/application.yml
---
environments:
production:
server:
port: 5000
./gradlew deployGr8jar
AWS Elastic Beanstalk is an easy-to-use service for deploying and scaling web applications and services developed with Java, .NET, PHP, Node.js, Python, Ruby, Go, and Docker on familiar servers such as Apache, Nginx, Passenger, and IIS.
# Elastic Beanstalk Nginx Configuration File in src/main/eb/.ebextensions/nginx/nginx.conf
user nginx;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 19200;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
include conf.d/*.conf;
map $http_upgrade $connection_upgrade {
default "upgrade";
}
server {
listen 80 default_server;
access_log /var/log/nginx/access.log main;
client_header_timeout 60;
client_body_timeout 60;
keepalive_timeout 60;
gzip off;
gzip_comp_level 4;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# Include the Elastic Beanstalk generated locations
include conf.d/elasticbeanstalk/*.conf;
# Increase upload body size
client_max_body_size 25m;
}
}
task beanstalkArchive(type: Zip, dependsOn: assemble) {
from 'src/main/eb'
from tasks.jar
}
beanstalk {
s3Endpoint = "s3-eu-west-1.amazonaws.com"
beanstalkEndpoint = "elasticbeanstalk.eu-west-1.amazonaws.com"
deployments {
gr8jar {
file = tasks.beanstalkArchive
application = 'dinte2018'
environment = 'gr8jar'
}
}
}
dependencies {
compile 'org.grails.plugins:sentry:11.7.4'
}
---
environments:
production:
server:
port: 5000
grails:
plugin:
sentry:
dsn: ${SENTRY_DSN}
# grails-app/conf/application.yml
---
environments:
production:
server:
port: 5000
grails:
plugin:
sentry:
dsn: ${SENTRY_DSN}
# enables Spring Security integration
springSecurityUser: true
<!doctype html>
<!-- grails-app/views/layouts/main.gsp -->
<html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<newrelic:browserTimingHeader/>
<!-- ... -->
</head>
<body>
<!-- ... -->
<newrelic:browserTimingFooter/>
</body>
</html>
└── src
└── main
└── eb
├── .ebextensions
│ ├── app.config
│ ├── files
│ │ ├── newrelic.jar
│ │ └── newrelic.yml.sh
│ ├── newrelic.sh
│ └── nginx
│ └── nginx.conf
└── Procfile
# src/main/eb/.ebextensions/files/newrelic.yml.sh
cat << EOF
# apply defaults
common: &default_settings
# apply custom settings
license_key: '$NR_LICENSE'
enable_auto_transaction_naming: false
app_name: $NR_APPNAME
EOF
#!/bin/sh
# src/main/eb/.ebextensions/newrelic.sh
# New Relic (Application monitoring)
mkdir /var/lib/newrelic
mv ./.ebextensions/files/newrelic*.jar /var/lib/newrelic/
bash ./.ebextensions/files/newrelic.yml.sh > /var/lib/newrelic/newrelic.yml
# New Relic deployment event
export AP_VERSION=`cat ./version`
java -Xms64m -Xmx124m -jar /var/lib/newrelic/newrelic.jar deployment --revision=$AP_VERSION
task prepareBeanstalkFiles() {
inputs.property('version', project.version)
outputs.file("$buildDir/beanstalk")
doLast {
file("$buildDir/beanstalk").mkdirs()
file("$buildDir/beanstalk/version").text = project.version
}
}
task beanstalkArchive(type: Zip, dependsOn: [assemble, prepareBeanstalkFiles]) {
from 'src/main/eb'
from "$buildDir/beanstalk" // include generated version file
from tasks.jar
}
# src/main/eb/.ebextensions/app.config
container_commands:
newrelic:
command: "bash -x .ebextensions/newrelic.sh"
# src/main/eb/Procfile
web: java -javaagent:/var/lib/newrelic/newrelic.jar -jar dinte2018.jar
jar {
archiveName = 'dinte2018.jar'
}
# src/main/eb/.ebextensions/newrelic-infra.sh
echo "license_key: $NR_LICENSE" | sudo tee -a /etc/newrelic-infra.yml
echo "display_name: `hostname`" | sudo tee -a /etc/newrelic-infra.yml
sudo curl -o /etc/yum.repos.d/newrelic-infra.repo \
https://download.newrelic.com/infrastructure_agent/linux/yum/el/6/x86_64/newrelic-infra.repo
sudo yum -q makecache -y --disablerepo='*' --enablerepo='newrelic-infra'
sudo yum install newrelic-infra -y
# src/main/eb/.ebextensions/app.config
container_commands:
newrelic:
command: "bash -x .ebextensions/newrelic.sh"
newrelic-infra:
command: "bash -x .ebextensions/newrelic-infra.sh"
# src/main/eb/.ebextensions/app.config
files:
"/etc/yum.repos.d/nginx.repo":
content: |
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/rhel/6/$basearch/
gpgcheck=0
enabled=1
container_commands:
newrelic:
command: "bash -x .ebextensions/newrelic.sh"
newrelic-infra:
command: "bash -x .ebextensions/newrelic-infra.sh"
nginx-nr-agent:
command: "bash -x .ebextensions/nginx-nr-agent.sh"
# src/main/eb/.ebextensions/nginx-nr-agent.sh
sudo yum install nginx-nr-agent -y
bash ./.ebextensions/files/nginx-nr-agent.ini.sh > /etc/nginx-nr-agent/nginx-nr-agent.ini
sudo service nginx-nr-agent start
# src/main/eb/.ebextensions/files/nginx-nr-agent.ini.sh
cat << EOF
# global settings
[global]
newrelic_license_key=$NR_LICENSE
poll_interval=60
# logging settings
[loggers]
keys=root
[handlers]
keys=consoleHandler,fileHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler,fileHandler
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[handler_fileHandler]
class=FileHandler
level=DEBUG
formatter=simpleFormatter
args=('/var/log/nginx-nr-agent.log','a',)
[formatter_simpleFormatter]
format=%(asctime)s %(name)s [%(levelname)s]: %(message)s
datefmt=
# data sources settings
[$NR_APPNAME]
name=$NR_APPNAME
url=http://127.0.0.1/nginx_status
EOF
# src/main/eb/.ebextensions/nginx/nginx.conf
# ...
server {
# ...
client_max_body_size 25m;
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
}
# ...
dependencies {
// ...
compile 'org.grails.plugins:newrelic:4.0.1'
compile 'com.palominolabs.metrics:metrics-new-relic:1.0.5'
compile 'org.grails.plugins:dropwizard-metrics:1.0.0.M3'
}
// grails-app/init/dinte2018/BootStrap.groovy
package dinte2018
import com.codahale.metrics.MetricFilter
import com.codahale.metrics.MetricRegistry
import com.palominolabs.metrics.newrelic.AllEnabledMetricAttributeFilter
import com.palominolabs.metrics.newrelic.NewRelicReporter
import java.util.concurrent.TimeUnit
class BootStrap {
MetricRegistry metricRegistry
def init = { servletContext ->
new NewRelicReporter(
metricRegistry,
'Deployment is not the End Metrics',
MetricFilter.ALL,
new AllEnabledMetricAttributeFilter(),
TimeUnit.SECONDS,
TimeUnit.MILLISECONDS,
'dinte2018.'
).start(1, TimeUnit.MINUTES)
}
def destroy = { }
}
// grails-app/services/dinte2018/UploadRestaurantFeaturedImageService.groovy
package dinte2018
import grails.plugin.dropwizard.metrics.meters.Metered
class UploadRestaurantFeaturedImageService {
def restaurantGormService
@Metered(value='uploadFeatureImage', useClassPrefix = true)
Restaurant uploadFeatureImage(FeaturedImageCommand cmd) {
byte[] bytes = cmd.featuredImageFile.bytes
String contentType = cmd.featuredImageFile.contentType
restaurantGormService.updateRestaurantFeaturedImage(
cmd.id,
cmd.version,
bytes,
contentType
)
}
}