Using docker in development can be very convenient, but running your actual app (you know, the one you’re coding) in docker introduces various headaches.
- Mounted volumes are slow and error-prone
- You need hacks and shortcuts to run any console/debug commands in containers
- Live updates on code changes are unreliable in docker
- Runtime is slower in docker
- Dependency updates are slower in docker
- Networking is more complicated with docker
What genuinely surprises me, is that often teams don’t consider the obvious: just run your app directly on your machine. I find it to be the sweet spot of dev setup. Let’s see what it would look like.
1. Use docker-compose for databases and external services
docker-compose.yml file in your app’s root and only declare your databases in it. For example, this file gives you
- Postgres on
- Redis on
- Fake S3 on
version: '3' services: postgres: image: postgres:10.3-alpine ports: - "5432:5432" volumes: - postgres-data:/var/lib/postgresql/data redis: image: redis:3.2.11-alpine ports: - "6379:6379" volumes: - redis-data:/data minio: image: minio/minio volumes: - minio-data:/data ports: - "9000:9000" entrypoint: sh command: -c "mkdir -p /data/dev /data/test && /usr/bin/minio server /data" environment: MINIO_ACCESS_KEY: access_key MINIO_SECRET_KEY: secret_key volumes: postgres-data: redis-data: minio-data:
2. Use asdf for language runtimes
.tool-versions file in app’s root. Here’s an example for elixir and node setup.
elixir 1.6.4-otp-20 erlang 20.2.4 nodejs 10.8.0
3. Setup everything
Now you can bootstrap the application by running
asdf install docker-compose up
and in another terminal you run the app itself:
That’s it. Now you have the benefit of quick and simple dev setup without giving up all the convenience of interacting with your app directly, without containers in the middle.
Bonus: How to make local Rails work with dockerized Postgres?
The cool part is that your
database.yml can be committed to the repo, it will always look the same:
default: adapter: postgresql username: postgres host: localhost development: <<: database: myapp_dev test: <<: database: myapp_test production: <<: database: myapp
However, there’s a minor issue when using this setup in Rails. You might get an error when trying to install the pg gem or run a
rake db:structure:dump command. Both of these actions rely on postgres being installed locally. To work around it simply add postgres to your
.tool-versions — asdf supports it. You will not be actually running this postgres, only using its cli as a client, and satisfying pg’s dependencies.