DEV Community

Jake Varness
Jake Varness

Posted on

Demystifying containers using Crystal, Amber, and Docker

If you're like me, you have heard a lot about Docker and containerization, but haven't fully tapped into it's potential, or you aren't sure why or how it can fit your use cases.

Like with all new technologies, there comes a learning curve, and with Docker there exists a curve, but thankfully there is a TON of documentation to help reduce the curve.

I'm going to try and explain things like I'm not a super duper noob, but this post is going to assume that you know Amber and Crystal well enough to make small changes to a web application. If you need to learn more about Amber and Crystal, I would highly recommend looking at the posts that Elias Perez has made, as they're very thorough and can help you gain a very good understanding of how Amber apps are created.

Generating an Amber App

To get started, I would just recommend generating your own amber app using the amber new command:

amber new <name_of_app>
Enter fullscreen mode Exit fullscreen mode

I'm currently working on implementing the Tour of Heroes tutorial application in Amber instead of Angular, but it's nowhere close to what I've written from this post.

Without providing any options to the amber new command, a new project is generated that uses PostgreSQL and Granite as it's DB and ORM. This normally isn't so bad, but when it comes to configuring databases I typically get pretty annoyed. Throughout my career I remember running into a lot of issues trying to configure Oracle databases, and just a few weeks ago I tried installing PostgreSQL in a Linux Mint VM before I gave up and installed a Xubuntu VM.

It gets really annoying when all you want to do is code, but you have to set up an infrastructure to run your app! This is tiring, doesn't get you any closer to the ultimate goal of writing and running your application, and even if you get your environment working, it's no guarantee that it'll be exactly like the ones your clients have.

If only there was a simpler thing we could do...

Don't Download Databases, Download Docker!

Seriously, if you're at this step, save yourself the trouble of downloading PostgreSQL and trying to get it to run. Downloading Docker, if you can believe this, is going to make things easier for you right now, as well as in the long run.

I downloaded Docker onto my Mac last night, and I was able to deploy my Amber app to a container on my machine within a half hour of downloading it. Without it, I probably would have spent a good chunk of time downloading PostgreSQL and attempting to stand up a DB instance, which is time I really could have spent coding.

If you have a simple application created, and you have Docker downloaded for your platform, head to your terminal, and use the following command to get your app running:

docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

By running docker-compose up, you're asking docker to compose your application using the configuration defined in the Dockerfile and docker-compose.yml files that were created when you generated your app. The -d option just tells Docker that once the images were built and they're running, run them in the background so that the running Docker process isn't still attached to your terminal session.

To see your new images running, run the command docker container ls -a and you'll see all the containers that Docker created and ran for you:

$ docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                    NAMES
459baf330231        tour-of-heroes      "amber watch"            4 minutes ago       Up 4 minutes     >3000/tcp   tourofheroes_app_1
cd860dfd3fc3        tour-of-heroes      "bash -c 'while ! nc…"   4 minutes ago       Exited (0) 4 minutes ago                            tourofheroes_migrate_1
b0a5fd0d4ce5        postgres            "docker-entrypoint.s…"   4 minutes ago       Up 4 minutes               5432/tcp                 tourofheroes_db_1
Enter fullscreen mode Exit fullscreen mode

What Did I Just Do?

Well, you locally deployed your first Docker image using docker-compose of course! But what did Docker do?

Take a look at the docker-compose.yml file, and you'll probably be able to piece together what happened. There are three services defined in the docker-compose.yml file: app, migrate, and db. The app and migrate services are services belonging to your Docker image, and the db service uses the postgres image so that you don't have to manage the db yourself. That's right: no configuring default admin users, no downloading of databases required.

Since the db service sets up the database, you'll need to migrate your Granite models into the database... Well, YOU won't need to, because Docker already created a container that did that for you! The migrate service will run all of the appropriate amber migrate commands to migrate the models into the database, as well as run any seeders that have been written for your project.

Lastly, there's the app service, which just runs your app as defined in your Dockerfile. Once this container starts running, the application is ready to be accessed by going to http://localhost:3000.

Making Changes to the App

With your Docker image running, you can actually make changes to your application and they will be reflected in your image!

I had asked Amber to generate a scaffold for me for a Hero model, but it wasn't smart enough to know that the plural of "hero" was "heroes" and not "heros". I went around and fixed all the places where "heros" was and it was immediately reflected in the application!

Amber is also cool enough to pull in Bootstrap 3.3.7 into the application via CDN by default, so I updated the index.slang file to show a star glyph when the hero is a "favorite" hero rather than "true" or "false".

Now, if you need to bring down the application, you can bring the application down using docker-compose down, but beware, for invoking down will bring down the app, migrate, AND db containers, and any info you had saved in there before will be lost.

You can safely rebuild the the Docker image for you application and bring it up by invoking:

docker-compose up -d --no-deps --build app
Enter fullscreen mode Exit fullscreen mode

This will rebuild only the application and not include any dependencies, such as the database. If you need to execute another migrate command, you can include the migrate at the end of the command.

Wrapping Up

If you read this, I hope you found it helpful or useful! Hopefully after reading this and maybe following along with it, you're a little more comfortable with containers. I know that going through this boosted my confidence a little!

Top comments (0)