Docker on macOS: Getting Started
In this Docker tutorial, you’ll learn Docker vocabulary and the commands for creating, inspecting and removing containers, networks and data volumes. You’ll learn how to run Docker containers in the background or foreground, and switch between the two; how to publish ports; how to connect a database app and a web app running in separate containers; and how to share directories between containers and your Mac and among containers. By Audrey Tam.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Docker on macOS: Getting Started
50 mins
- Getting Started
- Installing Docker
- Docker Terminology & Housekeeping
- Hello World
- Using Docker Commands
- Running a Web App in a Docker Container
- Publishing Ports
- Running a Web App With a Database
- Running CouchDB in a Docker Container
- Running CouchDB & Server in Docker Containers
- Where’s My Database?
- Mounting Volumes: Sharing Host & Container Files
- Persisting Databases After the Container Exits
- Sharing a Database With Another Docker Container
- Providing Local Files to a Docker Container
- Choosing Between Volume & Bind Mount
- --mount or --volume?
- Copying Files Between Host & Container
- Summary of Docker Commands
- Where to Go From Here?
Choosing Between Volume & Bind Mount
You’ve now seen two different ways to mount host directories in a container: couchdbVolume
is a volume, while the EmojiJournalServer
directory is a bind mount. The main differences between a volume and a bind mount are where it lives on the host file system, and whether you can access it directly through the host file system.
You bind-mount a specific path on your local system — like the EmojiJournalServer folder — to a specific path in the container — /root/project
. You can interact directly with the local directory and changes will appear in the container. Likewise, changes made by the container appear in Finder.
You create a volume by specifying a name, like couchdbVolume, in either a docker run
or a docker volume create
command. The volume lives in Docker’s storage directory, in the Docker engine on your local system. You cannot interact directly with the contents of this directory. You can mount it into containers, and you can inspect its metadata or remove it. Docker manages reading and writing files in the volume.
Another big difference is what happens when you expose an existing container directory.
If you bind-mount a local directory to an existing container directory, what’s in the local directory obscures the container directory’s contents — this is what happens if you bind-mount your local couchdb-config
directory to the CouchDB container’s local.d
directory. You effectively overwrite the container directory. Don’t worry, the original directory is still in the read-only image!
If you expose a container directory as a volume, its contents are copied into the volume on the host. This is what happened when you created couchdbVolume
with the CouchDB container’s /opt/couchdb/data
directory as its target.
--mount
or --volume
?
There are also two different options you can use to mount volumes or bind-mount local directories. They do the same thing — they just use different syntax.
The --mount
option is newer than --volume
. It uses comma-separated key=value
pairs, and the order of the keys doesn’t matter. This option doesn’t have a shorthand version.
The --volume
flag, shorthand -v
, has three colon-separated fields: the order matters, but you have to remember, or look up, the meaning of each field.
Docker documentation recommends using the --mount
option instead of the -v
option: it’s more verbose, but that makes it easier to understand and remember.
The following two commands are equivalent — they bind-mount the current local directory to a new /home
directory in the container:
docker run --mount type=bind,source=/`pwd`,target=/home ibmcom/kitura-ubuntu
docker run -v $PWD:/home ibmcom/kitura-ubuntu
The following two commands are equivalent — they create a volume in Docker’s storage directory:
docker run --mount source=KituraVolume,target=/Kitura-Starter ibmcom/kitura-ubuntu
type=volume
is the default.
docker run -v KituraVolume:/Kitura-Starter ibmcom/kitura-ubuntu
-v
option is a name, not a path, so Docker creates a volume, not a bind mount.
Both commands copy /Kitura-Starter
‘s contents into a volume named KituraVolume
. The Kitura container then mounts and uses KituraVolume
. You can mount KituraVolume
in other containers, to give them access to its contents.
You can specify read-only access:
docker run --mount source=KituraVolume,target=/Kitura-Starter,readonly --name kitura ibmcom/kitura-ubuntu
docker run -v KituraVolume:/Kitura-Starter:ro --name kitura ibmcom/kitura-ubuntu
Here’s yet another difference between the behavior of --mount
and --volume
, from Docker’s documentation:
- If you use
-v
or--volume
to bind-mount a file or directory that does not yet exist on the Docker host,-v
creates the endpoint for you. It is always created as a directory. - If you use
--mount
to bind-mount a file or directory that does not yet exist on the Docker host, Docker does not automatically create it for you, but generates an error.
Note that if you use -v
to bind-mount a directory that doesn’t exist on the host, to a directory that exists in the container, it will be created as an empty directory on the host, so its emptiness will obscure the original contents in the container. For example, if you try to copy the Kitura-Starter directory from the container to your local file system with -v $PWD/kitura-dir:Kitura-Starter
, all you’ll get are empty directories in both your file system and the container.
Copying Files Between Host & Container
If you just want to save a file or directory from a running Docker container to your local system, you can just copy it:
docker cp kitura:/Kitura-Starter .
You can also copy a file or directory from your local system to a container:
docker cp kilroy.txt kitura:/var/tmp
Summary of Docker Commands
You’ve seen a lot of Docker commands in this tutorial! Below is a list of them. Terms in square brackets, like [image]
, are placeholders for specific names or IDs.
The docker run
command:
docker run [options] [image] [command for -it options]
The docker run
options you’ve used in this tutorial:
- --detach / -d
- --env / -e [ENV_VAR=value]
- --interactive --tty / -it ... [command]
- --name [name]
- --network [network]
- --mount source=[volume],target=[container-dir]
- --publish / -p [host port]:[container port]
- --volume / -v [host-dir]:[container-dir]
The other Docker commands you’ve used in this tutorial (plus one or two related commands you haven’t seen):
- docker pull [image]
- docker images or docker image ls
- docker ps -a or docker container ls -a
- docker ps -a -q -f [filter condition]
- docker exec -it [container] bash
- docker stop [container]
- docker start [container]
- docker rm $(docker ps -a -q -f status=exited)
- docker rm $(docker stop $(docker ps -q))
- docker rm [container IDs or names]
- docker rmi [image] or docker image rm [image]
- docker container inspect [container]
- docker network create [network-name]
- docker network inspect [network-name]
- docker network ls
- docker network prune
- docker volume create [volume-name]
- docker volume inspect [volume-name]
- docker volume ls
- docker volume prune
- docker cp [container:container-path] [host-path]
- docker cp [host-path] [container:container-path]
Some useful ways to detach containers running in the foreground:
- Control-P-Q detaches without stopping the container
- If the container is in the foreground because you ran
docker run -it ... bash
, exit at the bash shell prompt stops the container. - If the container is in the foreground because you ran
docker exec -it ... bash
, exit at the bash shell prompt exits the bash shell but doesn’t stop the container.