July 21, 2026
Docker has been around since about 2013 as a way to run software in portable, reusable containers. This has allowed many software development teams to standardise some parts of their development stacks regardless of developer environments and attempt to give parity between environments on each step of the software development and release cycle.
For me though, it felt like it was solving a problem that I just didn’t have. I was already quite a few years into developing Ruby and Rails applications on my Mac hardware. The package management system that I was using, homebrew, had become quite robust and the applications that I was working on worked very well with it, usually requiring a Postgresql database and a Redis instance for the most part.
As well as my dependencies being quite simple a lot of the time, I also didn’t really change what I was working on a lot. By 2014 I started a run of jobs that were each quite long tenured and where I had also moved out of doing consulting work and into product companies. This change in type of role moved me away from working on several applications at once and into working on a company’s application, or group of applications/services that would all need to be able to be running at the same time, they did not need to be isolated from each other.
This, however, has come to an end for the time being. As with so many folks in 2026, I was faced with a redundancy earlier this year. I was very fortunate in that I was able to land a contract relatively quickly and keep moving, but it does land me in the positoin where I am more conscious of flexibility, being able to work on multiple things on the same laptop, that any job, no matter how entrenched you are in it, no matter how good your relationship with it is, is safe. I know that these are fairly personal things on what has (even though I have not posted for a long time) a largely technical blog, but it has affected how I look at my work, and my realtionship with it. That is I suppose a very long way to say, I’ve found myself wanting to be able to easily and quickly switch which dependencies I am working with at any given time. As such, Docker has finally made itself useful to me.
Now that I am working a contract, and am toying with some application ideas of my own, I want to be able to switch what I am doing quickly and easily. When I had two versions of PostgreSQL on the go as we upgraded at my last job, I would just switch between which I was running at any given time with homebrew. It was a bit clunky, but I didn’t have to do it much. It was fine. At new contracting, there are several services to run, often at once on my laptop as I do my work. The tooling for these services spins up docker containers that house each of the dependencies for those services. This has been great for quickly spinning up and down whichever I need aceess to. It got me thinking, I should do a similar thing so when I work on this app I have an idea for, I can quickly get my database up as the one I am running, run it docker, turn off the container when I am done for day/time being and then be able to spin up the containers I need when I am working on the day job.
It needs to be easy, or frankly, I am not interested. I had written off the idea of using Docker containers on my development laptop, probably unfairly, but also I just didn’t feel like I had a problem that needed to be solved by them. I don’t think I’ve ever worked on a project where the exact container that you use in development ends up running the application in staging or production, so I felt like I just didn’t really care that much. Now that it is useful to me, and I’ve been introduced into how easily something gotten running then shutdown again, I’ve decided it’s time to re evaluate that, so I have some rake tasks to get all this going.
To have any of these work on my development machine, I use a Macbook Air these days, I need to have Docker for Mac running. I just use the desktop app so I can easily containers that are running, but you can run it on the terminal if you prefer, but Docker will need to be running to set this up.
I’m just starting out an app, so I only need my PostgreSQL instance running in a Docker continer for now. The not deploying containers was not the only reason I did not really care for Docker as a development tool. Any project I worked on where folks suggested it as an option there was never any really great tooling around it. To use it now for myself, I’ve decided that that tooling was absolutely necessary to keep it easy to use. What do I need for that? I need to be able to start or stop my container with a single command.
I started by being able to start up PostgreSQL with a single command:
bx rails docker:postgres:start
and can stop it with:
bx rails docker:postgres:stop
To do this, some pretty simple code in a rake task:
# lib/tasks/docker.rake namespace :docker do namespace :postgres do CONTAINER_NAME = "personal-postgres" desc "Start the personal PostgreSQL Docker container" task :start do if system("docker inspect #{CONTAINER_NAME} > /dev/null 2>&1") sh "docker start #{CONTAINER_NAME}" else abort "Container '#{CONTAINER_NAME}' does not exist. Create it first with docker run." end end desc "Stop the personal PostgreSQL Docker container" task :stop do sh "docker stop #{CONTAINER_NAME}" end end end
And it running:
❯ bx rails docker:postgres:start docker start personal-postgres personal-postgres
This was a pretty good result, but I was not satisified for long. It very quickly occurred to me that a basic rails app, I still use Rails all the time unless I have a good reason not to, has other dependencies. I don’t have them yet, but they will be there in any app that is not trivial, at least Redis. This meant that I wanted to be able to start (and stop) any dependency that runs in Docker with a single command. This mean I needed to be able define the dependencies that could be started/stopped, and also trigger a command. Nothing too crazy, so adding to the file:
namespace :docker do SERVICES = %w[postgres].freeze # Existing code omitted desc "Start all Docker services" task start: SERVICES.map { "docker:#{_1}:start" } desc "Stop all Docker services" task stop: SERVICES.map { "docker:#{_1}:stop" } end
So now I can stop the containers I had running earlier:
❯ bx rails docker:stop docker stop personal-postgres personal-postgres
Now my PostgreSQL container can be stopped, by stopping all containers that are running, and I can start up my Docker dependencies:
❯ bx rails docker:start docker start personal-postgres personal-postgres
This is all great, but I realised I still had one complaint about running Docker as a development dependency, creating the container in the first place. It’s mostly academic for this project I have, I am the only one working on it, and only on one laptop, but I wanted to better equipped for how do I get an app up and running quickly from scratch if needed. New laptop, new person, whatever the reason. That means there is one missing piece. Get the containers up and running even if they do not exist. Not a big deal, just need to add a new task:
# lib/tasks/docker.rake namespace :docker do # Omitted existing code desc "Create the personal PostgreSQL Docker container" task :init do if system("docker inspect #{CONTAINER_NAME} > /dev/null 2>&1") puts "Container '#{CONTAINER_NAME}' already exists." else sh "docker run -d " \ "--name #{CONTAINER_NAME} " \ "-e POSTGRES_USER=#{ENV.fetch('POSTGRES_USER', 'postgres')} " \ "-e POSTGRES_PASSWORD=#{ENV.fetch('POSTGRES_PASSWORD', 'postgres')} " \ "-p #{ENV.fetch('POSTGRES_PORT', 5432)}:5432 " \ "-v personal-postgres-data:/var/lib/postgresql " \ "postgres:18" end end # Omitted existing code desc "Create all Docker services" task init: SERVICES.map { "docker:#{_1}:init" } # Omitted existing code end
This one involves a little more. It needs to know a POSTGRES_USER, a POSTGRES_PASSWORD and a POSTGRES_PORT to set up. By setting them up in my Rails application with dotenv:
# .env POSTGRES_HOST=host POSTGRES_PORT=5432 POSTGRES_USER=username POSTGRES_PASSWORD=password
They are then available for use in my database.yml for the rails app config:
# config/database.yml default: &default adapter: postgresql encoding: unicode host: <%= ENV.fetch("POSTGRES_HOST", "localhost") %> port: <%= ENV.fetch("POSTGRES_PORT", 5432) %> username: <%= ENV.fetch("POSTGRES_USER", "postgres") %> password: <%= ENV.fetch("POSTGRES_PASSWORD") %> max_connections: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> development: <<: *default database: development_database
With these files set, I am then able to just run the rake tasks, and I can create, start and stop a docker container for development of my Rails app. This allows me to easily isolate my own personal work from anything I am doing while contracting, quickly and easily switching between the different versions of dependencies when I need to.
Whilst for many folks writing software none of this is revolutionary or new, Docker has been around for over a decade after all. It did get me thinking though, not only about things like right tool for the job, but also, sometimes, the right time for the tool. I guessI am saying that what has changed recently is not anything about this tooling, it’s been me, my outlook, and now my recent change in circumstance that let me to have a problem that I didn’t think needed solving before. So whilst this is well trodden ground for many, if it helps you out or solves a problem for you as well, I am really happy about that, and I’d love to hear about it.
Comments?
I've changed how I run my blog now and have decided to not integrate comments into this new version. I am happy to answer any questions though, feel free to send me an email through the link at the top of the screen. Happy Programming.