I was in need to deploy a Grails application as a war on my Digitalocean instance.
The architecture i wanted to have was an Apache which redirects some calls to Tomcat (while manages others directly) and have my grails application deployed as a war on tomcat, responding without context path.You can see the final result here at www.appromocodes.com (at the moment of this article there is only a landing page open to the public!)
This post is strictly related to DigitalOcean setup and Ubuntu 14.04.
So, to be clear i want my app (which comes from a war called appromocodes.war) to respond to www.appromocodes.com and i want that phpmyadmin responds at www.appromocodes.com/phpmyadmin and i want to have some other virtualhosts possibilities open.
So here are the steps:
Install servers
First of all, i installed a LAMP using DO images (but i thin it's a common ubuntu LAMP installation) then i installed tomcat and in the end i installed phpmyadmin. DO has a very comprehensive list of tutorials on how to do this, so check out for them. They will guid you through standard ubuntu installationsEnable modjk
This guide gives you hint on how to connect Apache 2 and Tomcat 7 using (and installing) mod_jk but there are a few points such as modifiyng 000-default.conf which are not best practice so i'll give you my way. Install mod jk viasudo apt-get install libapache2-mod-jkthen configure tomcat to receive mod jk incoming traffic
sudo vim /etc/tomcat7/server.xmluncommenting
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />Now let's create a worker file for Apache via
sudo vim /etc/apache2/workers.propertiesAnd set this content:
# Define 1 real worker using ajp13Now to ask Apache to use this worker
worker.list=worker1
# Set properties for worker (ajp13)
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009
sudo vim /etc/apache2/mods-available/jk.conf
and change the JkWorkersFile property to
/etc/apache2/workers.propertiesNow the guide linked before told you to modify 000-default.conf but this is not the correct way. We will create a specific conf and add it to apache via a2ensite command (this guide is very clear).
Configure Apache
Let's create a file. In my example it is called appromocodes.com.conf under the sites-available Apache folder and put this content within:<VirtualHost *:80>As you can see this virtualhost responds to my www.appromocodes.com domain and pass any call to Tomcat via ajp. Only /phpmyadmin path is still controlled by Apache thanks to the JkUnMount directive.
ServerAdmin admin@appromocodes.com
ServerName appromocodes.com
ServerAlias www.appromocodes.com
DocumentRoot /var/lib/tomcat7/webapps/appromocodes/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
JkUnMount /phpmyadmin* worker1
JkMount /* worker1
</VirtualHost>
Now
sudo a2ensite appromocodes.com.confand your site configuration will be enabled (a2dissite command to disable it).
Ah, don't forget
sudo service apache2 restartto see changes enabled.
At this moment, apache serves correctly /phpmyadmin calls and redirect all the traffic for www.appromocodes.com to tomcat. If you want to create another virtualhost for another domain you will see that everything works correctly.
Configure Tomcat
Now that apache sends the traffic to tomcat, we must instruct tomcat on what to do with this traffic since any call to www.appromocodes.com will be redirected to www.appromocodes.com:8080 default site (even if we will not see the port number), but our app is deployed via war (or folder) with a specific context. At this moment (suppose i've already deployed my app on tomcat), my webapp will respond to www.appromocodes.com/appromocodes. We must still do something to achieve our final resultOk, so we could still use apache and define rewrite rules but tomcat offers "virtual hosts" too. It is not as comfortable as apache but it's a very good solution.
You can find tons of information on tomcat docs regarding Host tag used to define virtual hosts but one thing you must be aware is that you must pay attention because it's easy to get multiple deploys of the same webapplication so after struggling a lot i found a good way to proceed and achieve my targets.
Modify tomcat' server.xml in its Engine section in this way (this is my example obviously):
<Engine name="Catalina" defaultHost="localhost">I have bolded the different elements respect the original ones. This section is telling Tomcat that we have two different hosts: localhost and appromocodes.com host to manage.
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps" unpackWARs="false" autoDeploy="false">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
</Host>
<Host name="appromocodes.com" unpackWARs="false" autoDeploy="false">
<Alias>www.appromocodes.com</Alias>
</Host>
</Engine>
We have disabled autodeploys and war unpacking so tomcat will not do anything like this automatically (this will help avoid autoredeploy of a war in a first moment as a war and in a second as a directory after war extraction).
We are saying that both share the webapps folder (we could have specified another folder for appromocodes.com but it was useless now and remeber to give that folder tomcat7:tomcat7 ownership and privileges).
Now, as specifically stated in the Tomcat docs, if you want to have an app that responds without context, you must declare it in a folder called ROOT or in a war called ROOT.war.
But i don't want to rename it any time so this is what we can do.
Execute
sudo service tomcat7 restartand have a look at conf/Catalina. You will find a new folder called appromocodes.com. We ca now create a file called ROOT.xml in conf/Catalina/appromocodes.com with this content:
<ContextThis file will specify the ROOT application context for our appromocodes.com host and as you can see you can address any war file you want (or folder if you prefer).
docBase="/var/lib/tomcat7/webapps2/appromocodes.war"
path=""
reloadable="true"
/>
If you now restart tomcat
sudo service tomcat7 restartyou will see that it will deploy a ROOT folder under webapps folder (if we had specified a different one in the server.xml we would have find it there so we could have specific ROOT folder for any host) and that's it!
Now our app responds correctly to www.appromocodes.com and we won't find any /appromocodes context in any call!
It is fundamental to define an external ROOT.xml file otherwise you will be able to specify only a different context instead of the natural one (war filename or folder name) but not a ROOT context and you will be subject to multiple redeploys.
Ok but...this is a general process not a Grails specific one!
That's right! This guide is ok for any general war deploy and apache 2 plus tomcat 7 configuration, but i have specified Grails too since it shows you how you can start from a Grails application, package it as a war via grails war (or grails prod war) and then deploying it as a J2EE webapplication.
Somebody might say it is better to run-app directly. In this case you can also specify different port such as 80 and have grails running directly your app. But in this way you loose the possibility to use Apache applications such as phpmyadmin or wordpress combined with your java app. And really important: grails consume much more memory while tomcat requires a lot less for the same app.
That's all folk, hope you save time!
Nessun commento:
Posta un commento