1. Introduction
In the following tutorial, we'll learn how to use the packaging and deployment tools that can help you deploy your application on a production server.
Deploying your web application on a remote server is a crucial part
2. Packaging your web application
2.1 What's an application package ?
What we call package is a single compressed file containing everything needed to run your application. Packages are platform dependent: if you build your package on Linux, you'll get a package that can only be deployed on other Linux systems.
Crails application packages consist of five elements:
- Binaries which, when executed, launch your server or its tasks.
- Libraries collected from the packaging environment, and including the libraries that each of your binary rely on.
- Service file depending on the target (systemctl for Linux, rc file for FreeBSD), used to start and stop your web application.
-
Static files including the
public
folder from your project - Runtime directory which is the only element which should have both read and write access. This is where your processes will run.
2.2 Package command
The Crails Command Line Interface comes with a tool to package your application in a single step:
$ crails package
What this command does is, it first builds your application (like crails build
), then
creates a compressed archive (by default: application.tar.gz
) which we call a package.
The package command has several option, the first of which being:
$ crails package --mode Release
This is what you want to do when you're about to deploy a package meant for a production environment. The
Release
build will be safer and lighter.
package
command by running $ crails package -h
.
3. Deploying your web application
We know how to package our application, and that's great ! But the purpose of a package is to be deployed, so let's see how to do that !
First things first, deployments are performed through ssh
, so make sure you've got it
installed on your system.
3.1 Manual deployment
Deploying a crails package is pretty simple. The first step is to send the package to your server,
which can be done using scp
:
$ scp application.tar.gz user@127.0.0.1:/tmp/application.tar.gz $ ssh user@127.0.0.1
Where 127.0.0.1
is the IP of the server you're trying to reach, and user
the name of the user with which you want to use to connect to that server.
Now that we're connected, we need to get root access, which can typically be done through:
$ sudo su
Then, we extract our archive at the root of the machine:
$ cd / $ tar xf /tmp/application.tar.gz
And voilĂ ! You may now start your application with the following command:
$ /usr/local/bin/application_name/start.sh
Where application_name is the name you've given to your application when creating it with the
crails new
command (which you can customize by changing the name
variable in
the .crails
file at the root of your project).
Of course, the application will stop as soon as you leave the terminal. To have your application run in the background, we need to deploy it as a service... which is precisely the purpose of the next chapter.
3.2 Using the deploy command
If you have direct ssh access to your machine, then you can make your life simpler by just using the deploy command, such as:
$ crails deploy \ --hostname 127.0.0.1 \ --deploy-user user \ --sudo \ --pubkey \ --user webapp \ --group www
Wow, that was a lot of options ! Let's go over what those do:
--hostname
takes the hostname or IP address of the server you want to deploy to--deploy-user
is the userssh
will use to connect to the server--sudo
is used when the deploy-user will need to use thesudo
command to extract the package or configure the service. This is usually the case.--pubkey
meansssh
will authentify using your RSA public key. The deploy command also has option for password connection, but we recommend using an RSA key.--user
and--group
are the name of the user and groups which will be running the web application on the remote server.
The deploy command will first package your application, then deploy it. So once you are done developping, you're always just one command away to send your application live.
Note that if the user and group specified in your options don't already exist on your production environment, they will be created by the deploy command.
libssh
development files to be available on your system to build,
so if you didn't have it prepped when you last installed crails, the deploy command won't be available.
3.3 Environment
Your deployed application might require environment variables to define some instance-specific settings. That is probably the best way to define your database settings, for instance.
You can optionally provide your own environment files or variables, which will be compiled to a single file
and uploaded to /usr/share/crails-deploy
(the filename being your application name).
Use the --env
option to add environment variables:
$ crails deploy [options] --env VARIABLE1=example VARIABLE2=example
Or environment files:
$ crails deploy [options] --env example1.env example2.env ...
The environment file will be loaded when you start your application as a service (using
systemctl start my_application
on Linux, for instance).
Environment files should define variables using the following format:
DATABASE_URL="postgresql://user:password@localhost:5432/app" REDIS_URL="redis://localhost:5379"
3.4 FreeBSD jails
If you're using a FreeBSD server, you may want to deploy your application in a jail. That's a great idea ! And good for you, the deploy
command can help you with that !
Once you've created a jail, just use the --jail-path
option to deploy to a jail:
$ crails deploy \ --hostname 127.0.0.1 \ --deploy-user user \ --sudo --pubkey \ --jailpath /var/jails/webapp
When using jails, the --user
and --group
options will be relative to the jail,
and only the service file will be deployed outside of the jail.
3.5 Deploying pre-built packages
The methods we've seen before are all-in-one: they build, package and deploy your application all at once. What if you already have a packaged application at hand, and just want to deploy that package ?
In this case, we don't use the crails
command anymore, and switch to crails-deploy
:
$ crails-deploy \ --app-name application_name \ --package my_package.tar.gz \ --hostname 127.0.0.1 \ --sudo --pubkey \ --start /usr/local/bin/package_name/start.sh \ --stop /usr/local/bin/package_name/stop.sh
The option are the same as the ones for crails deploy
, except you must:
- specify a
--package
option pointing to the archive you wish to deploy, - specify the start/stop scripts using the
--start/
and
--stop
options, - set an application name using the
--app-name
option. This may be the same name as the package's.
Note that the same package can be deployed several time with different app-name
, and thus, different services, environment, logs and runtime directories. This means you can deploy several instances of the same package on the same machine.
crails-deploy is framework agnostic, and can work for projects even outside of the crails framework. Check out the project's README at crails-deploy's github page to learn more about this tool.
4. Packaging with Docker
It is best to ensure your packaging environment is the same as your production environment: it's a good way to
avoid the linking issues that could happen in cases where a system library (such as the C++ standard library,
or the openssl library) is provided by your production environment in a different version than on your
packaging environment.
With Linux, this result is pretty simple to achieve, using Docker to locally replicate your
production environment.
Which is why Crails comes with a set of tools to help you package your application using docker. Let's
take a look ! Firstly, make sure that the docker service is installed and running on your machine.
Then, go to the diretory of one of your crails project, and install the docker plugin:
$ crails plugins docker install
This will set you up by creating the following files:
File/Folder
Purpose
docker/
Where your docker machine are run and configured.
docker/base/Dockerfile
Docker configuration using the debian:sid
image.
docker/base/build-build2.sh
Build2 is the build manager for crails. This scripts will install build2 on your docker machine.
docker/base/build-crails.sh
This script will build the crails framework libraries used by your application.
docker/base/build-environment.sh
This file sets some build options used by the build-crails.sh script.
docker/base/build-odb-compiler.sh
Optional: present when you're using the odb plugin.
docker/base/build-comet.sh
Optional: present when you're using the comet plugin.
The base configuration is meant as an example: we can't really guesstimate what your own production
environment will look like, so it should serve as a template for the configurations you will create for
your servers.
4.1 Machine creation
Speaking of which, now that the docker plugin is installed, you can scaffold new docker machine configurations
with the following command:
$ crails plugins docker new --name my_machine --image ubuntu:22.04
Your new machine configuration will be created in docker/my_machine
.
4.2 Running a machine
While you should be perfectly able to build and run those docker machines, the Crails CLI
comes with a bunch of tool to do it for you.
4.2.1 Opening a shell
This is pretty useful for debugging and tinkering around: the shell command allows you to
launch your docker machine, and opens a shell to interact with its contents:
$ crails plugins docker shell --dockerfile my_machine
If it hasn't already been done, this command will need to build the docker machine first. That
might take a while, so be patient ! You can also use the -v
option to see the output
of docker as it builds the machine.
4.2.2 Running your application
For some reasons that are your own, you might prefer to run your application from a docker machine
rather than directly from your own system. There's a command for that:
$ crails plugins docker run --dockerfile my_machine --port 3001
4.2.3 Packaging your application
Lastly, the main purpose of the docker plugin: packaging your application for your target environment.
You can use the following command to create a package from a specific docker machine:
$ crails plugins docker package \
--dockerfile my_machine \
--output my_machine.tar.gz
The options of the crails package
command are all also available with this comannd.
4.2.4 Deploying your application
Similarly to the package command, you can also use the deploy command with the docker plugin, such as:
$ crails plugins docker deploy \
--dockerfile my_machine \
--hostname 192.168.0.15 \
--deploy-user user
The options of the crails deploy
command are all also available with this command.