Bring Docker Compose services to the shell
Ocean is a proof-of-concept tool that enables the use of Compose services directly from the shell. Essentially, instead of calling a service like this:
docker compose run --rm myservice <command>
Ocean enables calling it like a "native" program:
myservice <command>
I'm using Docker Compose for development purposes trough a Compose file that defines a bunch of what I call interactive services. These are basically a way to quickly use programs in the Docker context. For example, in a Ruby on Rails project, my Compose file may contain the following:
# Use Rails commands.
#
# Usage: docker compose run --rm rails [arguments]
#
# Examples: docker compose run --rm rails console
# docker compose run --rm rails db:create db:migrate
rails:
build: .
depends_on:
- postgres
entrypoint: bin/rails
profiles:
- interactive
Typing docker compose run --rm rails
is, of course, extremely not practical
and it's easy enough to setup aliases
alias dcr="docker compose run --rm"
So that running the Rails CLI becomes
dcr rails <command>
But I was wondering if I could go further and just type in rails
and it would
automatically run Rails in a Docker container if I was in a directory containing
the appropriate Docker Compose file. Ocean is the anwser to that question.
Ocean sets up shims for your services in ~/.ocean/shims
. By prepending this directory to the PATH,
Ocean intercepts the command execution, determines if there is a Compose file in the current
directory with the appropriate service defined and either runs the service or finds the first
matching executable in the remaining of the PATH.
Ocean is writter in Ruby, so you'll need a Ruby interpreter. If you don't have one already, the Ruby version offered via your package manager of choice should do the job. For Debian and derivatives:
sudo apt install ruby
Clone the repo, build and install the gem:
git clone https://github.com/durierem/ocean
cd ocean
gem build ocean.gemspec
gem install ocean-cli-0.2.0.gem
Then, initialize Ocean with:
ocean init
IMPORTANT MANUAL STEP: finally, add ~/.ocean/shims
to your PATH environement variable
Now you're ready to take the sea:
ocean up serviceA serviceB
serviceA
serviceB <command>
To see which services are currently shimmed:
ocean ls
In order to stop shimming:
ocean down serviceA
Ocean is currently in a POC state, there's a few things to point out:
- Shims are global, meaning that
which <command>
returns the shim path whether you're in a directory that contains a Compose file or not - Ruby is not the speediest language, depending on your machine, expect up to 100ms of delay for commands to start
- The Compose file must be named "docker-compose.yml"
- It is not shell aware, meaning that, among other things, the PATH must be manually modified and if the native command is not found, you get a Ruby error instead of your shell's traditional "command not found"
- The feature set is limited
- Edge cases and bugs are expected
Thanks to rbenv for introducing me on the concept of shims.
If you're interested in Dockerized development and you're a Rails developer, check out the Evil Martian's article "Ruby on Whales" that exposes and digs deep into how to build such setups.
It ends up introducing dip which fills a role similar to Ocean whilst being far more mature and production ready but requires an additional configuration file.
These are the sources of inspiration behind Ocean.
Why is it named Ocean? I don't know, I just think it's neat :)