Docker Compose allows you to define your multi-container application with all of its dependencies in a single file, then spin your application up in a single command.
$ docker-compose up
Starting ch09_server2_1
Starting ch09_server1_1
Starting ch09_server3_1
Creating ch09_control_machine_1
Attaching to ch09_server3_1, ch09_server1_1, ch09_server2_1, ch09_control_machine_1
control_machine_1 | [I 22:29:59.156 NotebookApp] Writing notebook server cookie secret to /root/.local/share/jupyter/runtime/notebook_cookie_secret
control_machine_1 | [I 22:29:59.208 NotebookApp] Serving notebooks from local directory: /home
control_machine_1 | [I 22:29:59.209 NotebookApp] 0 active kernels
control_machine_1 | [I 22:29:59.209 NotebookApp] The Jupyter Notebook is running at: http://0.0.0.0:8888/
control_machine_1 | [I 22:29:59.210 NotebookApp] Use Control-C to stop this server and shut down allkernels (twice to skip confirmation).
...
$ docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------------------
ch09_control_machine_1 docker-entrypoint.sh jupyt ... Up 0.0.0.0:8888->8888/tcp
ch09_server1_1 /usr/sbin/sshd -D Up 0.0.0.0:2221->22/tcp
ch09_server2_1 /usr/sbin/sshd -D Up 0.0.0.0:2223->22/tcp
ch09_server3_1 /usr/sbin/sshd -D Up 0.0.0.0:2222->22/tcp