# Docker Shell Pattern

## Don't let Docker complicate your development environment

Categories: docker

## Docker Docker Docker

I’ve been using Docker for many years now. During this time I’ve noticed that I can make life a little difficult for my self … and, undoubtedly, everyone else around me. For a brief moment, let me discuss my Docker journey in a few words:

### My Docker Journey

#### Phase: Ignorance

What is this thing? Why do I need another Vagrant?

#### Phase: Naivety

Ooooooh, it’s like apt; I can “install” and run Elasticsearch with a single command

#### Phase: Enlightened

It’s redefining the atomic unit of software development: Packaging. Distribution. Runtime with Containment / Isolation. All the Security

#### Phase: Pomposity

Everything should be in a container. Don’t you run zsh in a container too?

#### Phase: Bitter Pomposity

Yeah, so like, my auto-complete doesn’t work anymore because all these IDEs don’t understand that my build tools are containers. It’s so annoying. They need to get with the times

#### Phase: Angry Pomposity

Sigh. Yes, OSXFS sucks. Just install Linux

#### Phase: Rage

Did you update the Makefile without updating CI? You broke the fucking build again. Oh, it was me. Sorry mate 😅

NB: git commit --amend is your friend 😂

#### Phase: Indifference

I have all my dev tools installed locally and in containers

### What’s the Point?

Hopefully you recognise a few of these phases. It’s taken me a long time to realise:

1. You can’t force everyone to use Docker
2. You shouldn’t force yourself to use Docker
3. You should support agnostic development environments

I’m not saying this is new. I’m not suggesting I’m the only person that does this. I’m not going to try and convince you this is life-changing. This is me admitting that it took a very long time to establish some common sense when working on projects and providing my teams with sensible development environments.

## The Docker Shell Pattern

The idea is threefold:

1. Provide a Makefile
2. Include targets for dshell and dclean
3. Only use make targets

### Provide a Makefile

Seriously. I’ve seen so many, and created a few myself, ./bin/start.sh scripts over the last few years that I may passive aggressively snort if I see another. Just use a Makefile. It’s easier, I promise. Lets stop writing scripts with if [[ $1 == "start" ]];. • Provide small targets that provide a single purpose to be run • Provide goals that utilise two or more single purpose targets • ALWAYS provide an up target and sing it in the style of Serj Tankian when executing said target What’s the beauty of this? 1. (Almost) Every system has make pre-installed 2. You can use these targets to develop without Docker … shocking, I know #### Example lint: @mix format --check-formatted format: @mix format --check-equivalent deps: @mix deps.get compile: deps @mix compile up: @mix run --no-halt test: @MIX_ENV=test mix test${TESTS}

coveralls:
@MIX_ENV=test mix coveralls

clean:
@mix clean


### Include targets for dshell and dclean

Now … wouldn’t it be nice if we provided a simple interface for the people that want to use Docker?

Just run make dshell and you’ll be presented with a new bash terminal. Now you can execute your make targets like those sinful developers that don’t use Docker.

dshell:
# --service-ports publishes your ports, which you'd normally only get from docker-compose up
@docker-compose run --rm --service-ports --entrypoint=bash elixir

dclean:
@docker-compose down -v --rmi=local


## Profit

That’s it. I said it was simple. Use those make targets for local development, CI and within your Docker Shell for a happy, simpler, life.