Docker Jumpstart: Andrew Odewahn
Docker Jumpstart: Andrew Odewahn
Docker Jumpstart: Andrew Odewahn
Andrew Odewahn
Table of Contents
CHAPTER 1: Introduction 5
iii
Table of Contents
Cleaning up 35
iv
Introduction 1
Docker is a tool for packaging and shipping apps. Based on the idea of a ship-
ping container, it provides a standardized way for developers or system admin-
istrators to create lightweight images, or collections of images, for each ele-
ment of an application, and then easily and quickly deploy the image. Since the
image is standardized, it can be uniformly deployed on development or produc-
tion, leading to a much simpler workflow, faster development time for the dev
team, and lower management overhead for the ops team.
First, a quick overview of a few things Docker is:
• An open source tool that places a layer on top of Linux containers (LXC) to
make it simple to package and ship complex apps
• A tool for creating a layered filesystem; each layer is versioned and can be
shared across running instances, making for much more lightweight de-
ployments
• A company behind the project, as well as a site called the “Docker Hub”
for sharing containers
• A virtual machine. Unlike a true VM, a docker container does not also re-
quire a host OS, meaning it’s much slimmer than a real VM
• An infrastructure automation tool, like Puppet or Chef. Like those other
tools, Docker is a major player in the DevOps space, but its focus is
around running apps in a container environment, as opposed to repre-
senting a machine state.
This guide introduces the key ideas you’ll use again and again in Docker,
such as images, layers, containers, commits, tags, and so forth. The main things
to understand include:
5
CHAPTER 1: Introduction
The following table, taken from the “docker help” command, provides a
quick summary of the commands.
Command Description
ps List containers
6
Introduction
Command Description
wait Block until a container stops, then print its exit code
As you scan the list (which I’ve left in alphabetical order), you’ll notice 3 key
groups of commands:
This guide is organized along these same basic lines. First, we’ll cover how to
get Docker up and running on a Mac or Windows machine using a tool called
boot2docker. (If you’re using a Linux-based machine, you can skip this chapter.)
Next, we’ll talk about images and layers, and then talk about containers, which
are the “running” instances of an image. Next, we’ll talk about the Docker Hub,
which is a place where you can post your images, as well as find images main-
tained by other Docker users.
7
CHAPTER 1: Introduction
Although the examples might be a bit contrived, the goal of the guide is to
give you a quick introduction to the ideas you’ll use again and again as you ex-
plore Docker in depth.
8
Using boot2docker to run
Docker on a Mac or Windows 2
Docker’s underlying containerization technology only works on Linux. To use it
on a Mac or Windows, you must use a command-line tool called boot2docker
(http://boot2docker.io/) that installs a Linux virtual machine (or “VM”) on your
system. If you’re unfamiliar with VMs, they let you run a “guest” operating sys-
tem (like Linux) on your “host” operating system (like a Mac or Windows). For all
intents and purposes, the VM is another computer running “inside” your com-
puter -- it has its own operating system, filesystem, and network that can piggy-
back on the resources of the host OS in an isolated environment.
So, the idea behind boot2docker is really quite clever: since we can’t run
Docker natively on Windows or a Mac, we install a bare-bones Linux VM that can
run Docker, and then we communicate with it using a Docker client running on
our host (i.e., the terminal on our main OS). If you’ve ever used a package like
Postgres or MySql, it’s exactly the same idea: you have a client tool that you use
to issue commands to another server. The main difference is that our “docker”
process is running inside a VM, rather than as a native service.
This chapter will walk you through the installation process. Since both Dock-
er and boot2docker are changing so rapidly, rather than describe the detailed
steps here, I’ve provided an overview of the process so that you’ll understand
what’s happening.
Install boot2docker
Before you start, it’s a good idea to first set up SSH on your host machine so
that boot2docker can install your login credentials on the VM. Otherwise, you’ll
be prompted for a password whenever you log in. If you’re unfamiliar with SSH
or SSH keys, Appendix ??? will give you details of how to get set up.
First, download the installation package for your system. You can find Mac
(http://docs.docker.com/installation/mac/) and Windows (http://docs.dock-
er.com/installation/windows/) installation instructions on the Docker’s docu-
9
CHAPTER 2: Using boot2docker to run Docker on a Mac or Windows
$ boot2docker init
2014/08/11 13:30:58 Creating VM boot2docker-vm...
2014/08/11 13:30:58 Apply interim patch to VM boot2docker-vm
(https://www.virtualbox.org/ticket/12748)
2014/08/11 13:30:58 Setting NIC #1 to use NAT network...
2014/08/11 13:30:58 Port forwarding [ssh] tcp://127.0.0.1:2022 --
> :22
2014/08/11 13:30:58 Port forwarding [docker] tcp://127.0.0.1:2375
--> :2375
2014/08/11 13:30:58 Setting NIC #2 to use host-only network "vbox-
net4"...
2014/08/11 13:30:59 Setting VM storage...
2014/08/11 13:31:07 Done. Type `boot2docker up` to start the VM.
Once the box is created (it can take a few minutes because it has to down-
load the image), you run boot2docker up to boot up the box. Think of this as
turning your the new computer on. The box will start the Docker daemon in the
VM that listens for requests from the our client on our host. Here’s an example:
$ boot2docker up
2014/08/11 13:38:00 Waiting for VM to be started...
............
2014/08/11 13:38:36 Started.
2014/08/11 13:38:36 To connect the Docker client to the Docker dae-
mon, please set:
2014/08/11 13:38:36 export DOCKER_HOST=tcp://
192.168.59.104:2375
$ export DOCKER_HOST=tcp://192.168.59.104:2375
10
Install boot2docker
Since running the export command in the shell will only set the environment
variable temporarily, you should follow the process on your OS to make it per-
manent. On a Mac, add the following line to the ~/.bash_profile (http://stack-
overflow.com/questions/22502759/mac-os-x-10-9-setting-permanent-
environment-variables):
As you can see from the output, this command has pulled down the hello-
world (https://registry.hub.docker.com/_/hello-world/) repository from (more
on this in a later chapter) and printed the text “Hello from Docker.” If you’re see-
ing this message, then you’ve successfully installed boot2docker. Alternatively,
if you get a message like the following, you should doublecheck that you’ve set
the DOCKER_HOST environment variable correctly:
If you’ve installed an older version of boot2docker, you can (and should!) use
boot2docker itself to update the package. The commands are:
$ boot2docker stop
$ boot2docker download
$ boot2docker start
11
CHAPTER 2: Using boot2docker to run Docker on a Mac or Windows
$ boot2docker status
running
The following table, taken from “boot2docker help”, summarizes the various
commands.
Command Description
ssh [ssh- Start a shell on the VM using SSH. If you have not set up an SSH
command] key, you’ll be prompted for a password. (It’s “tcuser”)
down / stop /
Gracefully shutdown the VM.
halt
delete / de-
Delete the boot2docker VM and its disk image.
stroy
Displays selected settings for the VM, such as its memory size or
config / cfg
IP address
12
boot2docker Quick Reference
Command Description
You can also provide a variety of options to further customize the VM, such
as setting the amount of memory or the name of the box itself. Most of these
options appear to only work when the image is created (i.e., they only apply
then you’re doing “boos2docker init”). The following table summarizes the op-
tions from “boot2docker help”. (The actual output from the command shows
the default settings for each option.)
Option Description
13
CHAPTER 2: Using boot2docker to run Docker on a Mac or Windows
Here’s an example of how you’d created an image that used 4GB, rather than
the default 2GB.
By and large, boot2docker hides the nitty gritty details of working directly with
VirtualBox (https://www.virtualbox.org/), the underlying software that allows
us to run the VMs. However, there’s one particular situation -- opening a port
from your VM to your host machine -- where you’ll need to use the VirtualBox
itself. The most common use case for doing this is when you are developing
some custom app that is running within Docker, but you want to connect with it
in your browser.
14
Opening a port with VirtualBox
For example, say you’re writing a Rails application. You might pull down the
a Docker image that has a Ruby and Rails environment (https://regis-
try.hub.docker.com/u/stackbrew/rails/) installed, start the local development
server, and then try to connect to localhost:4567 to see the output, like you
would in a “normal” environment. By default, however, boot2docker only expo-
ses a few ports on the VM (port 2022 for SSH and port 2375 for the boot2docker
API), so instead of seeing your app, you’ll only see a “Cannot connect” page.
Fortunately, the fix for this is quite simple. VirtualBox has a command line
utility called “VBoxManage” that you can use to customize the box as it runs. To
expose a port, type something like this into your terminal:
This will create a port forwarding rule that in VirtualBox that will last until
you destroy the box. You can also create this rule in the VirtualBox GUI tool in
the “Settings -> Network -> Port Forwarding” screen, as shows in the next fig-
ure.
15
CHAPTER 2: Using boot2docker to run Docker on a Mac or Windows
You can find out more about this tool in the extensive VirtualBox documen-
tation (https://www.virtualbox.org/manual/UserManual.html) site.
16
Images: Layered filesystems 3
A Docker image represents a snapshot of a filesystem at a certain point in time.
As mentioned in the introduction, the image is composed of layers that pro-
gressively stack on top of each other; containers (running instances of an im-
age) can share these layers among them, which is one reason Docker is so much
lighter weight than a full VM, where nothing is generally shared.
Perhaps the best way to start (after you get Docker installed, of course!) is to
use “docker pull” to grab the latest release of Ubuntu (we’ll talk more about
where you’re actually pulling from in the chapter on the Docker Hub):
As you pull the image, you’ll see the progress of each dependent layer being
downloaded. Once all the layers are finished downloading (and there are a LOT
of layers for Ubuntu and all the versions), you can run docker images to get
information about the images on your system. Here’s an example:
$ docker images
REPOSITORY TAG IMAGE ID
CREATED VIRTUAL SIZE
ubuntu 14.04 c4ff7513909d 2 days
ago 225.4 MB
ubuntu latest c4ff7513909d 2 days
ago 225.4 MB
ubuntu 14.04.1 c4ff7513909d 2 days
ago 225.4 MB
17
CHAPTER 3: Images: Layered filesystems
If you want a granular view of the layers in in an image, you can use docker
history:
18
Images: Layered filesystems
• They can be reused. Docker keeps track of all the layers you’ve pulled. So,
if two images happen to have a layer in common (for example, if two im-
ages are built form the same base box), Docker will reuse the common
parts, and only pull the diffs.
• The layers are always additive, which can lead to really big sizes if you’re
not careful. For example, if you download a large file, make a commit, de-
lete the file, and then make another commit, that large file will still be
present in the layer history. We’ll come back to this idea again, so don’t
worry if it doesn’t make too much sense right now. Just remember that
layers are always additive.
19
Containers: Running instances
of an Image 4
A container is a running image that you start with the docker run command,
like this:
• OPTIONS. There are a LOT of options for the run command. We’ll cover
this in a bit more depth in the next shortly.
• IMAGE. The name of the image that the container should start from.
• COMMAND. The command that should run on the container when it starts.
Let’s try a simple command to to start a new container using the latest ver-
sion of Ubuntu. Once this container starts, you’ll be at a bash shell where you
can do cat /etc/os-release to see the release information about the OS:
Next, type this command in your running container to make a simple change
on the filesystem:
21
CHAPTER 4: Containers: Running instances of an Image
Now that you’ve verified the OS release and created a test file, here’s a bit
more detail about the options we’ve used in the RUN command:
• The OPTIONS “-it” tell Docker to make the container interactive and pro-
vide a tty (i.e., attach a terminal)
• The IMAGE is the “ubuntu:latest” image we pulled down. Note the reposi-
tory:tag format, which is used throughout docker. By default, the “latest”
tag is used, but if we were to use “ubuntu:precise” we’d be using Ubuntu
12.04.
• The COMMAND is “/bin/bash”, which starts a shell where you can log in
The cool thing is that once you’re in an interactive docker shell, you can do
anything you want, such as installing packages (via apt-get), code bases (using
git), or dependencies (using pip, gem, npm, or any other package manager du
jour.) You can then commit the container at any point to create a new image
that has your changes.
To see this in action, open a new terminal on your host machine and use
“docker ps” command to see some information about the running container:
$ docker ps
CONTAINER ID IMAGE COMMAND
CREATED STATUS PORTS NAMES
4afa46473802 ubuntu:14.04 /bin/bash 17
hours ago Up 39 seconds jol-
ly_perlman
• The CONTAINER_ID, a unique identifier you can use to refer to the con-
tainer in other commands (this is kind of like a process id in Linux)
• The IMAGE that was used when the container started
• The COMMAND used to start the container
• The time the underlying image was CREATED
• The uptime STATUS
• The exposed ports (lot’s more on this!)
• A human readable NAME that you can use in place of the ID (this is some-
thing you can also assign yourself, which we’ll get into shortly.)
As you can see, this command returns the changes that have happened on
the filesystem, which in our case is that we’ve changed the “/tmp” directory by
22
Docker RUN Quick Reference
adding a “hello.txt” file. Now let’s commit the changes we’ve made into a new
container:
Taking another look at docker images shows the effect; we now have a
new image called “hello_docker” that includes our “/tmp/hello.txt” file. Taking
a quick look at the container’s history shows how our change added a whop-
ping new 12 byte layer on top of the original layers of ubuntu:latest.
If you do docker ps again, you’ll see that the process has stopped.
The next chapter will provide much more detail on how to create your own con-
tainers and images using docker run, one of the most feature-rich commands in
Docker. Taken directly from docker help, this table is a useful quick reference
you can refer to as you go further with Docker.
23
CHAPTER 4: Containers: Running instances of an Image
Option Description
24
Docker RUN Quick Reference
Option Description
25
Building images with
Dockerfiles 5
As we saw in the Docker Walkthrough chapter, the general Docker workflow is:
# Comment
INSTRUCTION arguments
The following table summarizes the instructions; many of these options map
directly to option in the “docker run” command:
Command Description
ADD Copies a file from the host system onto the container
27
CHAPTER 5: Building images with Dockerfiles
Command Description
ENTRYPOINT
The base image to use in the build. This is mandatory and must be
FROM
the first command in the file.
Once you’ve created a Dockerfile and added all your instructions, you can
use it to build an image using the docker build command. The format for this
command is:
The build command results in a new image that you can start using docker
run, just like any other image. Each line in the Dockerfile will correspond to a
layer in the images’ commit history.
#
# Super simple example of a Dockerfile
#
FROM ubuntu:latest
MAINTAINER Andrew Odewahn "odewahn@oreilly.com"
28
Example of building an image from a Dockerfile
WORKDIR /home
As you can see, it’s pretty straightforward: we start from “ubuntu:latest,” in-
stall dependencies with the RUN command, add our code file with the ADD com-
mand, and then set the default directory for when the container starts. Once we
have a Dockerfile itself, we can build an image using docker build, like this:
The “-t” flag adds a tag to the image so that it gets a nice repository name
and tag. Also not the final “.”, which tells Docker to use the Dockerfile in the cur-
rent directory. Once you start the build, you’ll see it churn away for a while in-
stalling things, and when it completes, you’ll have a brand new image. Running
docker history will show you the effect of each command has on the overall
size of the file:
29
CHAPTER 5: Building images with Dockerfiles
file:c1472c26527df28498 192.5 MB
511136ea3c5a 14 months
ago 0 B
Finally, you can start the container itself with the following command:
Notice that in this example we’re running the Flask app directly when we
start the container, rather than just running the bash shell and starting it as
we’ve done in other examples.
Dockerfiles provide a relatively simple way to create a base image. And, be-
cause you can use the FROM command to chain Dockerfiles together into in-
creasingly complex images, you can do quite a lot, even with Docker’s (refresh-
ingly!) minimal command set. But, if you already have an existing IA tool (and
you should!), such as Chef (http://www.getchef.com/), Puppet (http://puppet-
labs.com/), Ansible (http://www.ansible.com/home), Salt (http://www.salt-
stack.com/), it’s very unlikely you could or even should rewrite everything. So, if
you’re in this situation what can you do?
I HAVE NO IDEA! I NEED TO RESEARCH THIS MORE, BUT I THINK YOU CAN
USE A TOOL LIKE Packer](http://www.packer.io/). MAYBE I CAN CONVINCE
Jeroen Janssens to do something with his Ansible stuff (https://github.com/
jeroenjanssens/data-science-at-the-command-line/tree/master/dst/build)
30
Creating your own Docker
Image 6
Now that we’ve got the basics, let’s make something a tiny bit more realistic: a
Flask (http://flask.pocoo.org/) app. In this section we’ll:
Again, the point here is not to show the best way to set up an environment,
but instead to illustrate the Docker commands and what they do. I’ll code de-
velopment environments in more detail later.
The nice thing about using a name is that you can use it in other docker
commands in place of the container id. For example, you can use this command
to see the top process running on the container. (Also, it’s worth noting that you
need to run this on a terminal on your host, not in the container itself.)
31
CHAPTER 6: Creating your own Docker Image
Now that we’ve got the container running, we install the dependencies we
need. First, since Flask is a Python micro framework, let’s check out what ver-
sion of Python we have:
This will churn away for a while updating various packages. Once it’s com-
plete, install python and pip:
This churns even longer, but once it’s done, you can install Flask:
Whew. That’s a lot of stuff to install, so let’s commit the image with a simple
commit message:
So, now if you check your “docker images” you’ll see the new repository:
32
Install our code
But, ugh, it doesn’t have a name -- it just shows up as “<none>”. We can use
docker tag to give our image a nice name, like this:
Finally, taking a quick look at the history shows that we’ve loaded about
160MB worth of new stuff onto our image:
33
CHAPTER 6: Creating your own Docker Image
As before, we’ll use the “-it” options to make it interactive, but we’re now
adding a couple of new settings:
• The “-p 5000:5000” option exposes port 5000 on the container and routes
it to port 5000 on the host. If you’re running Docker on a Mac, the confus-
ing thing to remember is that from the Docker container’s perspective,
the virtual machine is the host, so you’ll also need to expose port 5000
from the VM in order to see it on your “real” host OS. We’ll cover this In-
ception (http://en.wikipedia.org/wiki/Inception)-like step in the next sec-
tion.
• The “-w /home” option sets the working directory used when the contain-
er starts. Note that this must be an absolute path.
Once we’re in, we’ll grab our simple hello world file from this projects github
repo:
# wget https://raw.githubusercontent.com/odewahn/docker-jumpstart/
master/examples/hello.py
--2014-08-17 05:38:02-- https://raw.githubusercontent.com/odewahn/
docker-jumpstart/master/examples/hello.py
Resolving raw.githubusercontent.com (raw.githubusercontent.com)...
199.27.78.133
Connecting to raw.githubusercontent.com (raw.githubusercon-
tent.com)|199.27.78.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 149 [text/plain]
Saving to: 'hello.py'
100%
[===========================================================================>]
149 --.-K/s in 0s
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run(host='0.0.0.0')
Finally, once you’ve got the file, start the app. You should see something like
this:
34
View the flask app on your host machine
We’re ready for the big reveal. On a terminal on your host, try this command:
$ curl localhost:5000
If you’re running this on Linux as your host OS, you should see “Hello
World!” printed. If you’re running it on boot2docker on a Mac or Windows, you
most likely got this error:
As I mentioned earlier, when you started the container and told it to expose
port 5000, it exposed it on the virtual machine, not on your host. As described in
the chapter on boot2docker, you need to use VBoxManage to open the port
from the VM onto your host, like this:
You should now be able to connect to the simple app, like this:
$ curl localhost:5000
Hello World!
Cleaning up
If you’re really excited about your “Hello World!” Flask app, you should feel free
to commit it. Otherwise, let’s kill it. First, we need to figure out its ID, which
we’ll do using “docker ps”:
$ docker ps -a
CONTAINER ID IMAGE COMMAND
CREATED STATUS
PORTS NAMES
2f5ada6523c4 simple_flask:latest /bin/bash 3
days ago Up 34 minutes 0.0.0.0:5000->5000/
tcp nostalgic_goodall simple_flask
35
CHAPTER 6: Creating your own Docker Image
To verify it’s gone, lets run “docker ps” again, but this time add the “-a” op-
tion so that we see all containers:
$ docker ps -a
CONTAINER ID IMAGE COMMAND
CREATED STATUS
PORTS NAMES
2f5ada6523c4 simple_flask:latest /bin/bash 3
days ago Exited (-1) 2 seconds ago
nostalgic_goodall
55ba5b67cb28 simple_flask:latest /bin/bash 3
days ago Exited (0) 40 minutes ago
dreamy_mayer
6029929a1e53 ubuntu:latest /bin/bash 3
days ago Exited (0) 13 hours ago
naughty_leakey
ef9bd2df07c6 ubuntu:latest /bin/bash 4
days ago Exited (0) 13 hours ago
simple_flask
As you’ll see, although the container has stopped running (i.e., its status has
changed from Up to Exited), the container itself is still there. In fact, unless you
use the “-rm” option when you start a container, it will always leave this rem-
nant image behind. And, if left unchecked, after a while you’ll consume your en-
tire disk with stopped containers.
Why is it like this, you might ask? The answer lies in Docker’s need to get a
clean files state for a commit. In a container is running, it can mean that there
are open files or processes that could interfere with the ability to save the state
of the filesystem. So, rather than destroy the container automatically, Docker
saves it to enable you to get a nice, clean commit image. So, killing the image is
really the same as just pausing it.
So, to get rid of this ghost container, you need to use “docker rm”:
$ docker rm 2f5ada6523c4
2f5ada6523c4
But, what about all those other stopped containers hanging around? Never
fear! This great tip from Jim Hoskins (http://jimhoskins.com/) in Remove Un-
tagged Images From Docker (http://jimhoskins.com/2013/07/27/remove-
untagged-docker-images.html) shows a quick way to remove stopped contain-
ers in bulk:
36
Sharing images on Docker Hub 7
The Docker Hub (https://hub.docker.com) is a site where you store and share
images you create. Consciously modeled on GitHub (https://github.com/), the
site offers features like:
• Docker image hosting. Like GitHub, public images are free and private im-
ages are paid
• Collaborators who can push and pull the images
• Webhooks that are fired when a new image is pushed
• Statistics tracking, such as downloads and stars
There are two key ways to interact with the Docker Hub:
• The Web interface, where you can register, manage image metadata (de-
scription, etc), add or remove collaborators, and so forth. This is similar
to GitHub.
• The docker command line tool, where you can pull, push, or search for
images. This is similar to git.
There are a number of features specific Docker. One of the most interesting,
trusted builds (http://blog.docker.com/2013/11/introducing-trusted-builds/),
allow you to create signed images based on a Dockerfile in GitHub or BitBucket.
As with a CI/CD tool, the trusted build is triggered by a post commit hook on
your repo so that your image will also be up to date with your codebase. In ad-
dition, the image is flagged with a “trusted build” badge so that you can verity
its source.
Create an account
The first to using Docker hub is to sign up, which you can do on their Signup
page (https://hub.docker.com/account/signup/). You’ll be asked for an email
address, username, and a password. Once you login, you’ll see a project dash-
board that’s similar to other hosting sites:
37
CHAPTER 7: Sharing images on Docker Hub
Once you’ve set up your account, you use the docker login command
from your terminal so that you can pull and push images from your account.
(Note that you can also register with this command, as well, if you want to not
use the site.) Once you login, your docker will store your credentials in a file
called .dockercfg in your home directory.
One of the most basic things you can do with the Hub is search for other images
using docker search. Here, for example, are the first few results returned by
the docker search ubuntu command. As of this writing, we get over 1300
matches, so be prepared to wait a bit for the results.)
38
Searching for images
• Name. This is the name and namespace of the image. (More on namespa-
ces in a bit.)
• Description. This is metadata about the image from Docker Hub.
• Stars. The number of people who have “starred” the image
• Official. Whether or not the image comes from Docker, Inc. An “OK” in this
column helps provide some sense of security that the image has been
vetted.
• Automated. Whether or not the image is the result of an automated build.
While less authoritative than an “Offical” image, an automated image will
provide a link to the source GitHub or BitBucket repo on which the image
is based. This way you can at least review the contents of the image be-
fore you start it on your environment.
• Root. This is the namespace is reserved for “root” images maintained di-
rectly by Docker, Inc. Basically, it’s an “empty” space, and the names are
things like “ubuntu” or “debian.”
• User. This namespace is for users within the Docker Hub, such as “crash-
systems/gitlab-docker,” “mbentley/ubuntu-django-uwsgi-nginx,” or “sut-
tang/gollum”
39
CHAPTER 7: Sharing images on Docker Hub
Pulling an image
Pulling any of these images is simple: just use docker pull and whatever the
name is. For example, here’s how you pull all layers of the “stackbrew/ubuntu”
image:
As discussed in the chapter on images, you can also pull only the layers of
the latest build by adding “:latest” to the name. (Otherwise you’ll pull the full
history.)
Pushing an Image
Let’s try to push an image to the hub. Unlike the previous search and pull
commands, you must be logged in to push. If you’re not already logged in,
Docker will prompt you for your credentials
40
Pushing an Image
official images, in which case you probably don’t need this book!). So, let’s add
our username using the docker tag command:
Once you’ve retagged the image, you can push it to the Hub:
41
Additional Resources 8
This Jumpstart guide has only scratched the surface of Docker. This page is
meant as a kind of living resource, so if you find helpful tools or resources, send
me a pull request.
Docker has a booming ecosystem of tools. Here are a few of the more interest-
ing ones that I’d love to write a chapter about some day:
43