Docker & Django | Django vs. Rails
One of my goals for this project is to learn how to use Docker. Well, I’ve picked up a few things since my last article. Docker is a neat tool that containerizes ones entire project—code, runtime, tools, libraries and settings. This is useful for several reasons but the one that makes most sense to me is that it isolates one’s software from it’s environment.
Here’s a real-life example. As an API Specialist at Braintree, I review code submissions from candidates. Since Braintree offers server-side SDKs in six different languages, our team often receives submissions written in Java, Ruby, Python, .Net, PHP, and NodeJS. It’s not uncommon for our team to receive code submissions that make assumptions about the environment an dependencies needed to run the app. In some cases candidates submit a helpful README. In other cases, our team sinks time into configuring our environments just so we can run the code submission locally—if at all. What a pain. That’s where Docker would be a boon to these candidates. A container has everything needed within itself to run, therefore anybody can run that same container in pretty much any environment without the issues I mentioned above.
So, I’ve made a case for learning Docker. This isn’t a Docker tutorial, though. For that, I recommend the official getting started docs. That said, I’ve documented the commands I’ve been using frequently when working with Docker.
Docker & Django
Once I gained some proficiency with Docker, I dove into Django with the official tutorial. After I got my polls app running locally, I moved on to learning how to build a Docker image from my Django app. Enter the Dockerfile.
A Dockerfile contains a set of instructions that Docker will execute when building an image. They can include commands that a user would call on the command line. I wrote a Dockerfile that inherits a base image for Python3, makes directory for my project code, installs the requirements, and exposes the the container on port 8000. This last step is essential. When the container is instantiated from an image and the port is published, the container will listen on port 8000. Now, the host system can communicate with the container at localhost:8000. Note, when running the container I mapped my hosts port 5000 to my container’s port 8000 using docker run -p 5000:8000.
And with that, I have my simple Django app running in an isolated, contained environment that I have packaged in an image.
Django vs. Rails
I realized that Django is somewhat familiar to me because it shares several concepts with Rails, which is my programming mother tongue, so to speak. I immediately noticed that Django also follows an MVC pattern. However, Django’s interpretation of MVC is different from Rails’. When I began learning about views in Django, I thought I’d be writing templates and partials. I soon realized that what I was writing in Django views I could well have written in a Rails controller. After a little research, I found that this question comes up frequently. In essence, Django employs MTV—Model, Template, View. According to Django, a view describes what data is presented, not how that data is presented—how is left to templates.
I made a few other mental notes to orient myself to Django, coming from Rails:
- Routes are located in a url.py file and are defined with regex. Unfortunately, Django doesn’t have an equivalent to Rails’ resources :model that I’ve seen yet.
- Each model (including its view, templates, and tests) is, essentially, it’s own app in a Django project. This is in contrast to the Rails approach where the Models directory contains all models, the Controllers directory contains all controllers, and the Views directory contains all views.
- Django has an ORM, just like Rails.
- Django provides user authentication baked in. Rails users still have to rely on devise or get busy with some bcrypt.
- Django also has a super useful shortcuts package.
Here are the Django commands I’ve been using frequently:
That’s it for this update. Stay tuned for my next article in November where a functioning MVP of my app will be available to play with.