diff --git a/_data/toc.yaml b/_data/toc.yaml
index df44789c02..11d3e2f6dc 100644
--- a/_data/toc.yaml
+++ b/_data/toc.yaml
@@ -29,21 +29,21 @@ guides:
section:
- title: "Part 1: Getting started"
path: /get-started/
- - title: "Part 2: Our Application"
+ - title: "Part 2: The application"
path: /get-started/02_our_app/
- - title: "Part 3: Updating our Application"
+ - title: "Part 3: Update the application"
path: /get-started/03_updating_app/
- - title: "Part 4: Sharing Our Application"
+ - title: "Part 4: Share the application"
path: /get-started/04_sharing_app/
- - title: "Part 5: Persisting our DB"
+ - title: "Part 5: Persist the DB"
path: /get-started/05_persisting_data/
- - title: "Part 6: Using Bind Mounts"
+ - title: "Part 6: Use bind mounts"
path: /get-started/06_bind_mounts/
- - title: "Part 7: Multi-Container Applications"
+ - title: "Part 7: Multi-container apps"
path: /get-started/07_multi_container/
- - title: "Part 8: Using Docker Compose"
+ - title: "Part 8: Use Docker Compose"
path: /get-started/08_using_compose/
- - title: "Part 9: Image building tips"
+ - title: "Part 9: Image-building best practices"
path: /get-started/09_image_best/
- title: "Part 10: What next?"
path: /get-started/11_what_next/
diff --git a/get-started/02_our_app.md b/get-started/02_our_app.md
index da96971730..15d11d6570 100644
--- a/get-started/02_our_app.md
+++ b/get-started/02_our_app.md
@@ -18,23 +18,22 @@ think about how it will work for a large team, multiple developers, etc.
{: style="width:50%;" }
-
-## Getting our App
+## Get the app
Before we can run the application, we need to get the application source code onto
our machine. For real projects, you will typically clone the repo. But, for this tutorial,
we have created a ZIP file containing the application.
-1. [Download the App contents](https://github.com/docker/getting-started/tree/master/app). You can either pull the entire project or download it as a zip and extract the app folder out to get started with
+1. [Download the App contents](https://github.com/docker/getting-started/tree/master/app){:target="_blank" rel="noopener" class="_"}. You can either pull the entire project or download it as a zip and extract the app folder out to get started with
-1. Once extracted, use your favorite code editor to open the project. If you're in need of
- an editor, you can use [Visual Studio Code](https://code.visualstudio.com/). You should
+2. Once extracted, use your favorite code editor to open the project. If you're in need of
+ an editor, you can use [Visual Studio Code](https://code.visualstudio.com/){:target="_blank" rel="noopener" class="_"}. You should
see the `package.json` and two subdirectories (`src` and `spec`).
{: style="width:650px;margin-top:20px;"}
{: .text-center }
-## Building the App's Container Image
+## Build the app's container image
In order to build the application, we need to use a `Dockerfile`. A
Dockerfile is simply a text-based script of instructions that is used to
@@ -53,7 +52,7 @@ see a few flaws in the Dockerfile below. But, don't worry! We'll go over them.
Please check that the file `Dockerfile` has no file extension like `.txt`. Some editors may append this file extension automatically and this would result in an error in the next step.
-1. If you haven't already done so, open a terminal and go to the `app` directory with the `Dockerfile`. Now build the container image using the `docker build` command.
+2. If you haven't already done so, open a terminal and go to the `app` directory with the `Dockerfile`. Now build the container image using the `docker build` command.
```bash
docker build -t getting-started .
@@ -74,7 +73,7 @@ see a few flaws in the Dockerfile below. But, don't worry! We'll go over them.
The `.` at the end of the `docker build` command tells that Docker should look for the `Dockerfile` in the current directory.
-## Starting an App Container
+## Start an app container
Now that we have an image, let's run the application! To do so, we will use the `docker run`
command (remember that from earlier?).
@@ -90,13 +89,13 @@ command (remember that from earlier?).
background) and creating a mapping between the host's port 3000 to the container's port 3000.
Without the port mapping, we wouldn't be able to access the application.
-1. After a few seconds, open your web browser to [http://localhost:3000](http://localhost:3000).
+2. After a few seconds, open your web browser to [http://localhost:3000](http://localhost:3000).
You should see our app!
{: style="width:450px;margin-top:20px;"}
{: .text-center }
-1. Go ahead and add an item or two and see that it works as you expect. You can mark items as
+3. Go ahead and add an item or two and see that it works as you expect. You can mark items as
complete and remove items. Your frontend is successfully storing items in the backend!
Pretty quick and easy, huh?
@@ -109,7 +108,6 @@ If you take a quick look at the Docker Dashboard, you should see your two contai

-
## Recap
In this short section, we learned the very basics about building a container image and created a
diff --git a/get-started/03_updating_app.md b/get-started/03_updating_app.md
index 0f710c5343..dbddc87c0a 100644
--- a/get-started/03_updating_app.md
+++ b/get-started/03_updating_app.md
@@ -1,5 +1,5 @@
---
-title: "Updating our Application"
+title: "Update the application"
keywords: get started, setup, orientation, quickstart, intro, concepts, containers, docker desktop
description: Making changes to our example learning application
---
@@ -13,7 +13,7 @@ would like to transition it to the following:
Pretty simple, right? Let's make the change.
-## Updating our Source Code
+## Update the source code
1. In the `src/static/js/app.js` file, update line 56 to use the new empty text.
@@ -22,13 +22,13 @@ Pretty simple, right? Let's make the change.
+
You have no todo items yet! Add one above!
```
-1. Let's build our updated version of the image, using the same command we used before.
+2. Let's build our updated version of the image, using the same command we used before.
```bash
docker build -t getting-started .
```
-1. Let's start a new container using the updated code.
+3. Let's start a new container using the updated code.
```bash
docker run -dp 3000:3000 getting-started
@@ -46,14 +46,12 @@ running. The reason this is a problem is because that container is using the hos
only one process on the machine (containers included) can listen to a specific port. To fix this,
we need to remove the old container.
-
-## Replacing our Old Container
+## Replace the old container
To remove a container, it first needs to be stopped. Once it has stopped, it can be removed. We have two
ways that we can remove the old container. Feel free to choose the path that you're most comfortable with.
-
-### Removing a container using the CLI
+### Remove a container using the CLI
1. Get the ID of the container by using the `docker ps` command.
@@ -61,14 +59,14 @@ ways that we can remove the old container. Feel free to choose the path that you
docker ps
```
-1. Use the `docker stop` command to stop the container.
+2. Use the `docker stop` command to stop the container.
```bash
# Swap out with the ID from docker ps
docker stop
```
-1. Once the container has stopped, you can remove it by using the `docker rm` command.
+3. Once the container has stopped, you can remove it by using the `docker rm` command.
```bash
docker rm
@@ -80,7 +78,7 @@ ways that we can remove the old container. Feel free to choose the path that you
>to the `docker rm` command. For example: `docker rm -f `
>
-### Removing a container using the Docker Dashboard
+### Remove a container using the Docker Dashboard
If you open the Docker dashboard, you can remove a container with two clicks! It's certainly
much easier than having to look up the container ID and remove it.
@@ -88,14 +86,13 @@ much easier than having to look up the container ID and remove it.
1. With the dashboard opened, hover over the app container and you'll see a collection of action
buttons appear on the right.
-1. Click on the trash can icon to delete the container.
+2. Click on the trash can icon to delete the container.
-1. Confirm the removal and you're done!
+3. Confirm the removal and you're done!

-
-### Starting our updated app container
+### Start the updated app container
1. Now, start your updated app.
@@ -103,13 +100,11 @@ much easier than having to look up the container ID and remove it.
docker run -dp 3000:3000 getting-started
```
-1. Refresh your browser on [http://localhost:3000](http://localhost:3000) and you should see your updated help text!
+2. Refresh your browser on [http://localhost:3000](http://localhost:3000) and you should see your updated help text!
{: style="width:55%" }
{: .text-center }
-
-
## Recap
While we were able to build an update, there were two things you might have noticed:
diff --git a/get-started/04_sharing_app.md b/get-started/04_sharing_app.md
index dab29c6963..f92114a4e3 100644
--- a/get-started/04_sharing_app.md
+++ b/get-started/04_sharing_app.md
@@ -1,26 +1,25 @@
---
-title: "Sharing Our Application"
+title: "Share the application"
keywords: get started, setup, orientation, quickstart, intro, concepts, containers, docker desktop, docker hub, sharing
redirect_from:
- /get-started/part3/
description: Sharing our image we built for our example application so we can run it else where and other developers can use it
---
-
Now that we've built an image, let's share it! To share Docker images, you have to use a Docker
registry. The default registry is Docker Hub and is where all of the images we've used have come from.
-## Create a Repo
+## Create a repo
-To push an image, we first need to create a repo on Docker Hub.
+To push an image, we first need to create a repository on Docker Hub.
-1. Go to [Docker Hub](https://hub.docker.com) and log in if you need to.
+1. Go to [Docker Hub](https://hub.docker.com){:target="_blank" rel="noopener" class="_"} and log in if you need to.
-1. Click the **Create Repository** button.
+2. Click the **Create Repository** button.
-1. For the repo name, use `getting-started`. Make sure the Visibility is `Public`.
+3. For the repo name, use `getting-started`. Make sure the Visibility is `Public`.
-1. Click the **Create** button!
+4. Click the **Create** button!
If you look on the right-side of the page, you'll see a section named **Docker commands**. This gives
an example command that you will need to run to push to this repo.
@@ -28,7 +27,7 @@ an example command that you will need to run to push to this repo.
{: style=width:75% }
{: .text-center }
-## Pushing our Image
+## Push the image
1. In the command line, try running the push command you see on Docker Hub. Note that your command
will be using your namespace, not "docker".
@@ -44,16 +43,16 @@ an example command that you will need to run to push to this repo.
To fix this, we need to "tag" our existing image we've built to give it another name.
-1. Login to the Docker Hub using the command `docker login -u YOUR-USER-NAME`.
+2. Login to the Docker Hub using the command `docker login -u YOUR-USER-NAME`.
-1. Use the `docker tag` command to give the `getting-started` image a new name. Be sure to swap out
+3. Use the `docker tag` command to give the `getting-started` image a new name. Be sure to swap out
`YOUR-USER-NAME` with your Docker ID.
```bash
docker tag getting-started YOUR-USER-NAME/getting-started
```
-1. Now try your push command again. If you're copying the value from Docker Hub, you can drop the
+4. Now try your push command again. If you're copying the value from Docker Hub, you can drop the
`tagname` portion, as we didn't add a tag to the image name. If you don't specify a tag, Docker
will use a tag called `latest`.
@@ -61,22 +60,21 @@ an example command that you will need to run to push to this repo.
docker push YOUR-USER-NAME/getting-started
```
-## Running our Image on a New Instance
+## Run the image on a new instance
Now that our image has been built and pushed into a registry, let's try running our app on a brand
new instance that has never seen this container image! To do this, we will use Play with Docker.
-1. Open your browser to [Play with Docker](http://play-with-docker.com).
+1. Open your browser to [Play with Docker](http://play-with-docker.com){:target="_blank" rel="noopener" class="_"}.
-1. Log in with your Docker Hub account.
+2. Log in with your Docker Hub account.
-1. Once you're logged in, click on the "+ ADD NEW INSTANCE" link in the left side bar. (If you don't see it, make your browser a little wider.) After a few seconds, a terminal window will be opened in your browser.
+3. Once you're logged in, click on the "+ ADD NEW INSTANCE" link in the left side bar. (If you don't see it, make your browser a little wider.) After a few seconds, a terminal window will be opened in your browser.
{: style=width:75% }
{: .text-center }
-
-1. In the terminal, start your freshly pushed app.
+4. In the terminal, start your freshly pushed app.
```bash
docker run -dp 3000:3000 YOUR-USER-NAME/getting-started
@@ -84,7 +82,7 @@ new instance that has never seen this container image! To do this, we will use P
You should see the image get pulled down and eventually start up!
-1. Click on the 3000 badge when it comes up and you should see the app with your modifications! Hooray!
+5. Click on the 3000 badge when it comes up and you should see the app with your modifications! Hooray!
If the 3000 badge doesn't show up, you can click on the "Open Port" button and type in 3000.
## Recap
diff --git a/get-started/05_persisting_data.md b/get-started/05_persisting_data.md
index 2679216531..5f0cf905a6 100644
--- a/get-started/05_persisting_data.md
+++ b/get-started/05_persisting_data.md
@@ -1,5 +1,5 @@
---
-title: "Persisting our DB"
+title: "Persist the DB"
keywords: get started, setup, orientation, quickstart, intro, concepts, containers, docker desktop
description: Making our DB persistent in our application
---
@@ -7,13 +7,13 @@ description: Making our DB persistent in our application
In case you didn't notice, our todo list is being wiped clean every single time
we launch the container. Why is this? Let's dive into how the container is working.
-## The Container's Filesystem
+## The container's filesystem
When a container runs, it uses the various layers from an image for its filesystem.
Each container also gets its own "scratch space" to create/update/remove files. Any
changes won't be seen in another container, _even if_ they are using the same image.
-### Seeing this in Practice
+### See this in practice
To see this in action, we're going to start two containers and create a file in each.
What you'll see is that the files created in one container aren't available in another.
@@ -29,7 +29,7 @@ What you'll see is that the files created in one container aren't available in a
commands (why we have the `&&`). The first portion picks a single random number and writes
it to `/data.txt`. The second command is simply watching a file to keep the container running.
-1. Validate we can see the output by `exec`ing into the container. To do so, open the Dashboard and click the first action of the container that is running the `ubuntu` image.
+2. Validate we can see the output by `exec`ing into the container. To do so, open the Dashboard and click the first action of the container that is running the `ubuntu` image.
{: style=width:75% }
@@ -48,7 +48,7 @@ What you'll see is that the files created in one container aren't available in a
You should see a random number!
-1. Now, let's start another `ubuntu` container (the same image) and we'll see we don't have the same
+3. Now, let's start another `ubuntu` container (the same image) and we'll see we don't have the same
file.
```bash
@@ -58,24 +58,24 @@ What you'll see is that the files created in one container aren't available in a
And look! There's no `data.txt` file there! That's because it was written to the scratch space for
only the first container.
-1. Go ahead and remove the first container using the `docker rm -f` command.
+4. Go ahead and remove the first container using the `docker rm -f` command.
-## Container Volumes
+## Container volumes
With the previous experiment, we saw that each container starts from the image definition each time it starts.
While containers can create, update, and delete files, those changes are lost when the container is removed
and all changes are isolated to that container. With volumes, we can change all of this.
-[Volumes](/storage/volumes/) provide the ability to connect specific filesystem paths of
+[Volumes](../storage/volumes.md) provide the ability to connect specific filesystem paths of
the container back to the host machine. If a directory in the container is mounted, changes in that
directory are also seen on the host machine. If we mount that same directory across container restarts, we'd see
the same files.
There are two main types of volumes. We will eventually use both, but we will start with **named volumes**.
-## Persisting our Todo Data
+## Persist the todo data
-By default, the todo app stores its data in a [SQLite Database](https://www.sqlite.org/index.html) at
+By default, the todo app stores its data in a [SQLite Database](https://www.sqlite.org/index.html){:target="_blank" rel="noopener" class="_"} at
`/etc/todos/todo.db`. If you're not familiar with SQLite, no worries! It's simply a relational database in
which all of the data is stored in a single file. While this isn't the best for large-scale applications,
it works for small demos. We'll talk about switching this to a different database engine later.
@@ -95,31 +95,31 @@ Every time you use the volume, Docker will make sure the correct data is provide
docker volume create todo-db
```
-1. Stop the todo app container once again in the Dashboard (or with `docker rm -f `), as it is still running without using the persistent volume.
+2. Stop the todo app container once again in the Dashboard (or with `docker rm -f `), as it is still running without using the persistent volume.
-1. Start the todo app container, but add the `-v` flag to specify a volume mount. We will use the named volume and mount
+3. Start the todo app container, but add the `-v` flag to specify a volume mount. We will use the named volume and mount
it to `/etc/todos`, which will capture all files created at the path.
```bash
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
```
-1. Once the container starts up, open the app and add a few items to your todo list.
+4. Once the container starts up, open the app and add a few items to your todo list.
{: style="width: 55%; " }
{: .text-center }
-1. Remove the container for the todo app. Use the Dashboard or `docker ps` to get the ID and then `docker rm -f ` to remove it.
+5. Remove the container for the todo app. Use the Dashboard or `docker ps` to get the ID and then `docker rm -f ` to remove it.
-1. Start a new container using the same command from above.
+6. Start a new container using the same command from above.
-1. Open the app. You should see your items still in your list!
+7. Open the app. You should see your items still in your list!
-1. Go ahead and remove the container when you're done checking out your list.
+8. Go ahead and remove the container when you're done checking out your list.
Hooray! You've now learned how to persist data!
->**Pro-tip**
+>**Note**
>
>While named volumes and bind mounts (which we'll talk about in a minute) are the two main types of volumes supported
>by a default Docker engine installation, there are many volume driver plugins available to support NFS, SFTP, NetApp,
@@ -127,7 +127,7 @@ Hooray! You've now learned how to persist data!
>environment with Swarm, Kubernetes, etc.
>
-## Diving into our Volume
+## Dive into the volume
A lot of people frequently ask "Where is Docker _actually_ storing my data when I use a named volume?" If you want to know,
you can use the `docker volume inspect` command.
@@ -150,7 +150,7 @@ docker volume inspect todo-db
The `Mountpoint` is the actual location on the disk where the data is stored. Note that on most machines, you will
need to have root access to access this directory from the host. But, that's where it is!
->**Accessing Volume data directly on Docker Desktop**
+>**Accessing volume data directly on Docker Desktop**
>
>While running in Docker Desktop, the Docker commands are actually running inside a small VM on your machine.
>If you wanted to look at the actual contents of the Mountpoint directory, you would need to first get inside
diff --git a/get-started/06_bind_mounts.md b/get-started/06_bind_mounts.md
index bb1fbd1a92..b6665c262b 100644
--- a/get-started/06_bind_mounts.md
+++ b/get-started/06_bind_mounts.md
@@ -1,5 +1,5 @@
---
-title: "Using bind mounts"
+title: "Use bind mounts"
keywords: get started, setup, orientation, quickstart, intro, concepts, containers, docker desktop
description: Using bind mounts in our application
---
@@ -13,13 +13,13 @@ used to provide additional data into containers. When working on an application,
mount our source code into the container to let it see code changes, respond, and let us see the changes right
away.
-For Node-based applications, [nodemon](https://npmjs.com/package/nodemon) is a great tool to watch for file
+For Node-based applications, [nodemon](https://npmjs.com/package/nodemon){:target="_blank" rel="noopener" class="_"} is a great tool to watch for file
changes and then restart the application. There are equivalent tools in most other languages and frameworks.
-## Quick Volume Type Comparisons
+## Quick volume type comparisons
Bind mounts and named volumes are the two main types of volumes that come with the Docker engine. However, additional
-volume drivers are available to support other uses cases ([SFTP](https://github.com/vieux/docker-volume-sshfs), [Ceph](https://ceph.com/geen-categorie/getting-started-with-the-docker-rbd-volume-plugin/), [NetApp](https://netappdvp.readthedocs.io/en/stable/), [S3](https://github.com/elementar/docker-s3-volume), and more).
+volume drivers are available to support other uses cases ([SFTP](https://github.com/vieux/docker-volume-sshfs){:target="_blank" rel="noopener" class="_"}, [Ceph](https://ceph.com/geen-categorie/getting-started-with-the-docker-rbd-volume-plugin/){:target="_blank" rel="noopener" class="_"}, [NetApp](https://netappdvp.readthedocs.io/en/stable/){:target="_blank" rel="noopener" class="_"}, [S3](https://github.com/elementar/docker-s3-volume){:target="_blank" rel="noopener" class="_"}, and more).
| | Named Volumes | Bind Mounts |
| - | ------------- | ----------- |
@@ -28,8 +28,7 @@ volume drivers are available to support other uses cases ([SFTP](https://github.
| Populates new volume with container contents | Yes | No |
| Supports Volume Drivers | Yes | No |
-
-## Starting a Dev-Mode Container
+## Start a dev-mode container
To run our container to support a development workflow, we will do the following:
@@ -41,7 +40,7 @@ So, let's do it!
1. Make sure you don't have any previous `getting-started` containers running.
-1. Run the following command. We'll explain what's going on afterwards:
+2. Run the following command. We'll explain what's going on afterwards:
```bash
docker run -dp 3000:3000 \
@@ -67,7 +66,7 @@ So, let's do it!
running `yarn install` to install _all_ dependencies and then running `yarn run dev`. If we look in the `package.json`,
we'll see that the `dev` script is starting `nodemon`.
-1. You can watch the logs using `docker logs -f `. You'll know you're ready to go when you see this...
+3. You can watch the logs using `docker logs -f `. You'll know you're ready to go when you see this...
```bash
docker logs -f
@@ -82,7 +81,7 @@ So, let's do it!
When you're done watching the logs, exit out by hitting `Ctrl`+`C`.
-1. Now, let's make a change to the app. In the `src/static/js/app.js` file, let's change the "Add Item" button to simply say
+4. Now, let's make a change to the app. In the `src/static/js/app.js` file, let's change the "Add Item" button to simply say
"Add". This change will be on line 109.
```diff
@@ -90,16 +89,15 @@ So, let's do it!
+ {submitting ? 'Adding...' : 'Add'}
```
-1. Simply refresh the page (or open it) and you should see the change reflected in the browser almost immediately. It might
+5. Simply refresh the page (or open it) and you should see the change reflected in the browser almost immediately. It might
take a few seconds for the Node server to restart, so if you get an error, just try refreshing after a few seconds.
{: style="width:75%;"}
{: .text-center }
-1. Feel free to make any other changes you'd like to make. When you're done, stop the container and build your new image
+6. Feel free to make any other changes you'd like to make. When you're done, stop the container and build your new image
using `docker build -t getting-started .`.
-
Using bind mounts is _very_ common for local development setups. The advantage is that the dev machine doesn't need to have
all of the build tools and environments installed. With a single `docker run` command, the dev environment is pulled and ready
to go. We'll talk about Docker Compose in a future step, as this will help simplify our commands (we're already getting a lot
diff --git a/get-started/07_multi_container.md b/get-started/07_multi_container.md
index 49e2dcdba6..b0d8ad7298 100644
--- a/get-started/07_multi_container.md
+++ b/get-started/07_multi_container.md
@@ -3,6 +3,7 @@ title: "Multi container apps"
keywords: get started, setup, orientation, quickstart, intro, concepts, containers, docker desktop
description: Using more than one container in our application
---
+
Up to this point, we have been working with single container apps. But, we now want to add MySQL to the
application stack. The following question often arises - "Where will MySQL run? Install it in the same
container or run it separately?" In general, **each container should do one thing and do it well.** A few
@@ -20,8 +21,7 @@ And there are more reasons. So, we will update our application to work like this

{: .text-center }
-
-## Container Networking
+## Container networking
Remember that containers, by default, run in isolation and don't know anything about other processes
or containers on the same machine. So, how do we allow one container to talk to another? The answer is
@@ -29,8 +29,7 @@ or containers on the same machine. So, how do we allow one container to talk to
> If two containers are on the same network, they can talk to each other. If they aren't, they can't.
-
-## Starting MySQL
+## Start MySQL
There are two ways to put a container on a network: 1) Assign it at start or 2) connect an existing container.
For now, we will create the network first and attach the MySQL container at startup.
@@ -41,7 +40,7 @@ For now, we will create the network first and attach the MySQL container at star
docker network create todo-app
```
-1. Start a MySQL container and attach it to the network. We're also going to define a few environment variables that the
+2. Start a MySQL container and attach it to the network. We're also going to define a few environment variables that the
database will use to initialize the database (see the "Environment Variables" section in the [MySQL Docker Hub listing](https://hub.docker.com/_/mysql/)).
```bash
@@ -66,14 +65,11 @@ For now, we will create the network first and attach the MySQL container at star
You'll also see we specified the `--network-alias` flag. We'll come back to that in just a moment.
->**Pro-tip**
->
->You'll notice we're using a volume named `todo-mysql-data` here and mounting it at `/var/lib/mysql`, which is
->where MySQL stores its data. However, we never ran a `docker volume create` command. Docker recognizes we want
->to use a named volume and creates one automatically for us.
->
+ >**Note**
+ >
+ >You'll notice we're using a volume named `todo-mysql-data` here and mounting it at `/var/lib/mysql`, which is where MySQL stores its data. However, we never ran a `docker volume create` command. Docker recognizes we want to use a named volume and creates one automatically for us.
-1. To confirm we have the database up and running, connect to the database and verify it connects.
+3. To confirm we have the database up and running, connect to the database and verify it connects.
```bash
docker exec -it mysql -p
@@ -103,8 +99,7 @@ For now, we will create the network first and attach the MySQL container at star
Hooray! We have our `todos` database and it's ready for us to use!
-
-## Connecting to MySQL
+## Connect to MySQL
Now that we know MySQL is up and running, let's use it! But, the question is... how? If we run
another container on the same network, how do we find the container (remember each container has its own IP
@@ -119,7 +114,7 @@ which ships with a _lot_ of tools that are useful for troubleshooting or debuggi
docker run -it --network todo-app nicolaka/netshoot
```
-1. Inside the container, we're going to use the `dig` command, which is a useful DNS tool. We're going to look up
+2. Inside the container, we're going to use the `dig` command, which is a useful DNS tool. We're going to look up
the IP address for the hostname `mysql`.
```bash
@@ -155,8 +150,7 @@ which ships with a _lot_ of tools that are useful for troubleshooting or debuggi
What this means is... our app only simply needs to connect to a host named `mysql` and it'll talk to the
database! It doesn't get much simpler than that!
-
-## Running our App with MySQL
+## Run your app with MySQL
The todo app supports the setting of a few environment variables to specify MySQL connection settings. They are:
@@ -165,21 +159,12 @@ The todo app supports the setting of a few environment variables to specify MySQ
- `MYSQL_PASSWORD` - the password to use for the connection
- `MYSQL_DB` - the database to use once connected
->**warning**
->Setting Connection Settings via Env Vars
->While using env vars to set connection settings is generally ok for development, it is **HIGHLY DISCOURAGED**
->when running applications in production. Diogo Monica, the former lead of security at Docker,
->[wrote a fantastic blog post](https://diogomonica.com/2017/03/27/why-you-shouldnt-use-env-variables-for-secret-data/)
->explaining why.
->
->A more secure mechanism is to use the secret support provided by your container orchestration framework. In most cases,
->these secrets are mounted as files in the running container. You'll see many apps (including the MySQL image and the todo app)
->also support env vars with a `_FILE` suffix to point to a file containing the variable.
->
->As an example, setting the `MYSQL_PASSWORD_FILE` var will cause the app to use the contents of the referenced file
->as the connection password. Docker doesn't do anything to support these env vars. Your app will need to know to look for
->the variable and get the file contents.
-
+>**Warning**
+>
+>**Setting Connection Settings via Env Vars**
+>
+>While using env vars to set connection settings is generally ok for development, it is **HIGHLY DISCOURAGED** when running applications in production. Diogo Monica, the former lead of security at Docker, [wrote a fantastic blog post](https://diogomonica.com/2017/03/27/why-you-shouldnt-use-env-variables-for-secret-data/){:target="_blank" rel="noopener" class="_"} explaining why. A more secure mechanism is to use the secret support provided by your container orchestration framework. In most cases, these secrets are mounted as files in the running container. You'll see many apps (including the MySQL image and the todo app) also support env vars with a `_FILE` suffix to point to a file containing the variable. As an example, setting the `MYSQL_PASSWORD_FILE` var will cause the app to use the contents of the referenced file as the connection password. Docker doesn't do anything to support these env vars. Your app will need to know to look for the variable and get the file contents.
+{: .warning}
With all of that explained, let's start our dev-ready container!
@@ -211,7 +196,7 @@ With all of that explained, let's start our dev-ready container!
sh -c "yarn install && yarn run dev"
```
-1. If we look at the logs for the container (`docker logs `), we should see a message indicating it's
+2. If we look at the logs for the container (`docker logs `), we should see a message indicating it's
using the mysql database.
```
@@ -225,9 +210,9 @@ With all of that explained, let's start our dev-ready container!
Listening on port 3000
```
-1. Open the app in your browser and add a few items to your todo list.
+3. Open the app in your browser and add a few items to your todo list.
-1. Connect to the mysql database and prove that the items are being written to the database. Remember, the password
+4. Connect to the mysql database and prove that the items are being written to the database. Remember, the password
is **secret**.
```bash
diff --git a/get-started/08_using_compose.md b/get-started/08_using_compose.md
index 75ecbb651e..1562b479f3 100644
--- a/get-started/08_using_compose.md
+++ b/get-started/08_using_compose.md
@@ -1,10 +1,10 @@
---
-title: "Using Docker Compose"
+title: "Use Docker Compose"
keywords: get started, setup, orientation, quickstart, intro, concepts, containers, docker desktop
description: Making our lives easier with Compose for our application
---
-[Docker Compose](/compose/) is a tool that was developed to help define and
+[Docker Compose](../compose/index.md) is a tool that was developed to help define and
share multi-container applications. With Compose, we can create a YAML file to define the services
and with a single command, can spin everything up or tear it all down.
@@ -15,12 +15,11 @@ on GitHub/GitLab doing exactly this now.
So, how do we get started?
-## Installing Docker Compose
+## Install Docker Compose
If you installed Docker Desktop/Toolbox for either Windows or Mac, you already have Docker Compose!
Play-with-Docker instances already have Docker Compose installed as well. If you are on
-a Linux machine, you will need to install Docker Compose using
-[the instructions here](/compose/install/).
+a Linux machine, you will need to [install Docker Compose](../compose/install.md).
After installation, you should be able to run the following and see version information.
@@ -28,20 +27,19 @@ After installation, you should be able to run the following and see version info
docker-compose version
```
-
-## Creating our Compose File
+## Create the Compose file
1. At the root of the app project, create a file named `docker-compose.yml`.
-1. In the compose file, we'll start off by defining the schema version. In most cases, it's best to use
- the latest supported version. You can look at the [Compose file reference](https://docs.docker.com/compose/compose-file/)
+2. In the compose file, we'll start off by defining the schema version. In most cases, it's best to use
+ the latest supported version. You can look at the [Compose file reference](../compose/compose-file/index.md)
for the current schema versions and the compatibility matrix.
```yaml
version: "3.7"
```
-1. Next, we'll define the list of services (or containers) we want to run as part of our application.
+3. Next, we'll define the list of services (or containers) we want to run as part of our application.
```yaml
version: "3.7"
@@ -51,8 +49,7 @@ docker-compose version
And now, we'll start migrating a service at a time into the compose file.
-
-## Defining the App Service
+## Define the app service
To remember, this was the command we were using to define our app container.
@@ -93,7 +90,7 @@ docker run -dp 3000:3000 `
image: node:12-alpine
```
-1. Typically, you will see the command close to the `image` definition, although there is no requirement on ordering.
+2. Typically, you will see the command close to the `image` definition, although there is no requirement on ordering.
So, let's go ahead and move that into our file.
```yaml
@@ -106,9 +103,9 @@ docker run -dp 3000:3000 `
```
-1. Let's migrate the `-p 3000:3000` part of the command by defining the `ports` for the service. We will use the
- [short syntax](https://docs.docker.com/compose/compose-file/#short-syntax-1) here, but there is also a more verbose
- [long syntax](https://docs.docker.com/compose/compose-file/#long-syntax-1) available as well.
+3. Let's migrate the `-p 3000:3000` part of the command by defining the `ports` for the service. We will use the
+ [short syntax](../compose/compose-file/index.md#short-syntax-1) here, but there is also a more verbose
+ [long syntax](../compose/compose-file/index.md#long-syntax-1) available as well.
```yaml
version: "3.7"
@@ -121,8 +118,8 @@ docker run -dp 3000:3000 `
- 3000:3000
```
-1. Next, we'll migrate both the working directory (`-w /app`) and the volume mapping (`-v "$(pwd):/app"`) by using
- the `working_dir` and `volumes` definitions. Volumes also has a [short](https://docs.docker.com/compose/compose-file/#short-syntax-3) and [long](https://docs.docker.com/compose/compose-file/#long-syntax-3) syntax.
+4. Next, we'll migrate both the working directory (`-w /app`) and the volume mapping (`-v "$(pwd):/app"`) by using
+ the `working_dir` and `volumes` definitions. Volumes also has a [short](../compose/compose-file/index.md#short-syntax-3) and [long](../compose/compose-file/index.md#long-syntax-3) syntax.
One advantage of Docker Compose volume definitions is we can use relative paths from the current directory.
@@ -140,7 +137,7 @@ docker run -dp 3000:3000 `
- ./:/app
```
-1. Finally, we need to migrate the environment variable definitions using the `environment` key.
+5. Finally, we need to migrate the environment variable definitions using the `environment` key.
```yaml
version: "3.7"
@@ -161,8 +158,7 @@ docker run -dp 3000:3000 `
MYSQL_DB: todos
```
-
-### Defining the MySQL Service
+### Define the MySQL service
Now, it's time to define the MySQL service. The command that we used for that container was the following:
@@ -199,10 +195,10 @@ docker run -d `
image: mysql:5.7
```
-1. Next, we'll define the volume mapping. When we ran the container with `docker run`, the named volume was created
+2. Next, we'll define the volume mapping. When we ran the container with `docker run`, the named volume was created
automatically. However, that doesn't happen when running with Compose. We need to define the volume in the top-level
`volumes:` section and then specify the mountpoint in the service config. By simply providing only the volume name,
- the default options are used. There are [many more options available](https://docs.docker.com/compose/compose-file/#volume-configuration-reference) though.
+ the default options are used. There are [many more options available](../compose/compose-file.md#volume-configuration-reference) though.
```yaml
version: "3.7"
@@ -219,7 +215,7 @@ docker run -d `
todo-mysql-data:
```
-1. Finally, we only need to specify the environment variables.
+3. Finally, we only need to specify the environment variables.
```yaml
version: "3.7"
@@ -272,14 +268,13 @@ volumes:
todo-mysql-data:
```
-
-## Running our Application Stack
+## Run the application stack
Now that we have our `docker-compose.yml` file, we can start it up!
1. Make sure no other copies of the app/db are running first (`docker ps` and `docker rm -f `).
-1. Start up the application stack using the `docker-compose up` command. We'll add the `-d` flag to run everything in the
+2. Start up the application stack using the `docker-compose up` command. We'll add the `-d` flag to run everything in the
background.
```bash
@@ -298,7 +293,7 @@ Now that we have our `docker-compose.yml` file, we can start it up!
You'll notice that the volume was created as well as a network! By default, Docker Compose automatically creates a
network specifically for the application stack (which is why we didn't define one in the compose file).
-1. Let's look at the logs using the `docker-compose logs -f` command. You'll see the logs from each of the services interleaved
+3. Let's look at the logs using the `docker-compose logs -f` command. You'll see the logs from each of the services interleaved
into a single stream. This is incredibly useful when you want to watch for timing-related issues. The `-f` flag "follows" the
log, so will give you live output as it's generated.
@@ -315,16 +310,13 @@ Now that we have our `docker-compose.yml` file, we can start it up!
view the logs for a specific service, you can add the service name to the end of the logs command (for example,
`docker-compose logs -f app`).
->**Pro tip** Waiting for the DB before starting the app
->
->When the app is starting up, it actually sits and waits for MySQL to be up and ready before trying to connect to it.
->Docker doesn't have any built-in support to wait for another container to be fully up, running, and ready
->before starting another container. For Node-based projects, you can use the
->[wait-port](https://github.com/dwmkerr/wait-port) dependency. Similar projects exist for other languages/frameworks.
+ >**Waiting for the DB before starting the app**
+ >
+ >When the app is starting up, it actually sits and waits for MySQL to be up and ready before trying to connect to it. Docker doesn't have any built-in support to wait for another container to be fully up, running, and ready before starting another container. For Node-based projects, you can use the [wait-port](https://github.com/dwmkerr/wait-port){:target="_blank" rel="noopener" class="_"} dependency. Similar projects exist for other languages/frameworks.
-1. At this point, you should be able to open your app and see it running. And hey! We're down to a single command!
+4. At this point, you should be able to open your app and see it running. And hey! We're down to a single command!
-## Seeing our App Stack in Docker Dashboard
+## See the app stack in Docker Dashboard
If we look at the Docker Dashboard, we'll see that there is a group named **app**. This is the "project name" from Docker
Compose and used to group the containers together. By default, the project name is simply the name of the directory that the
@@ -338,13 +330,12 @@ quickly see what container is our app and which container is the mysql database.

-
-## Tearing it All Down
+## Tear it all down
When you're ready to tear it all down, simply run `docker-compose down` or hit the trash can on the Docker Dashboard
for the entire app. The containers will stop and the network will be removed.
->**Warning**
+>**Warning**
>
>Removing Volumes
>
@@ -352,11 +343,11 @@ for the entire app. The containers will stop and the network will be removed.
>remove the volumes, you will need to add the `--volumes` flag.
>
>The Docker Dashboard does _not_ remove volumes when you delete the app stack.
+{: .warning}
Once torn down, you can switch to another project, run `docker-compose up` and be ready to contribute to that project! It really
doesn't get much simpler than that!
-
## Recap
In this section, we learned about Docker Compose and how it helps us dramatically simplify the defining and
diff --git a/get-started/09_image_best.md b/get-started/09_image_best.md
index cad13ae6b1..771a4bc7a2 100644
--- a/get-started/09_image_best.md
+++ b/get-started/09_image_best.md
@@ -1,12 +1,13 @@
---
-title: "Image building tips"
+title: "Image-building best practices"
keywords: get started, setup, orientation, quickstart, intro, concepts, containers, docker desktop
description: Tips for building the images for our application
---
-## Security Scanning
+
+## Security scanning
When you have built an image, it is good practice to scan it for security vulnerabilities using the `docker scan` command.
-Docker has partnered with [Snyk](http://snyk.io) to provide the vulnerability scanning service.
+Docker has partnered with [Snyk](http://snyk.io){:target="_blank" rel="noopener" class="_"} to provide the vulnerability scanning service.
For example, to scan the `getting-started` image you created earlier in the tutorial, you can just type
@@ -39,15 +40,15 @@ vulnerabilities are discovered, but it might look something like this:
The output lists the type of vulnerability, a URL to learn more, and importantly which version of the relevant library
fixes the vulnerability.
-There are several other options, which you can read about in the [docker scan documentation](https://docs.docker.com/engine/scan/).
+There are several other options, which you can read about in the [docker scan documentation](../engine/scan/index.md).
-As well as scanning your newly built image on the command line, you can also [configure Docker Hub](https://docs.docker.com/docker-hub/vulnerability-scanning/)
+As well as scanning your newly built image on the command line, you can also [configure Docker Hub](../docker-hub/vulnerability-scanning.md)
to scan all newly pushed images automatically, and you can then see the results in both Docker Hub and Docker Desktop.
{: style=width:75% }
{: .text-center }
-## Image Layering
+## Image layering
Did you know that you can look at what makes up an image? Using the `docker image history`
command, you can see the command that was used to create each layer within an image.
@@ -82,15 +83,14 @@ command, you can see the command that was used to create each layer within an im
the newest layer at the top. Using this, you can also quickly see the size of each layer, helping
diagnose large images.
-1. You'll notice that several of the lines are truncated. If you add the `--no-trunc` flag, you'll get the
+2. You'll notice that several of the lines are truncated. If you add the `--no-trunc` flag, you'll get the
full output (yes... funny how you use a truncated flag to get untruncated output, huh?)
```bash
docker image history --no-trunc getting-started
```
-
-## Layer Caching
+## Layer caching
Now that you've seen the layering in action, there's an important lesson to learn to help decrease build
times for your container images.
@@ -127,7 +127,7 @@ a change to the `package.json`. Make sense?
CMD ["node", "src/index.js"]
```
-1. Create a file named `.dockerignore` in the same folder as the Dockerfile with the following contents.
+2. Create a file named `.dockerignore` in the same folder as the Dockerfile with the following contents.
```ignore
node_modules
@@ -135,14 +135,14 @@ a change to the `package.json`. Make sense?
`.dockerignore` files are an easy way to selectively copy only image relevant files.
You can read more about this
- [here](https://docs.docker.com/engine/reference/builder/#dockerignore-file).
+ [here](../engine/reference/builder.md#dockerignore-file).
In this case, the `node_modules` folder should be omitted in the second `COPY` step because otherwise,
it would possibly overwrite files which were created by the command in the `RUN` step.
For further details on why this is recommended for Node.js applications and other best practices,
have a look at their guide on
- [Dockerizing a Node.js web app](https://nodejs.org/en/docs/guides/nodejs-docker-webapp/).
+ [Dockerizing a Node.js web app](https://nodejs.org/en/docs/guides/nodejs-docker-webapp/){:target="_blank" rel="noopener" class="_"}.
-1. Build a new image using `docker build`.
+3. Build a new image using `docker build`.
```bash
docker build -t getting-started .
@@ -183,9 +183,9 @@ a change to the `package.json`. Make sense?
You'll see that all layers were rebuilt. Perfectly fine since we changed the Dockerfile quite a bit.
-1. Now, make a change to the `src/static/index.html` file (like change the `` to say "The Awesome Todo App").
+4. Now, make a change to the `src/static/index.html` file (like change the `` to say "The Awesome Todo App").
-1. Build the Docker image now using `docker build -t getting-started .` again. This time, your output should look a little different.
+5. Build the Docker image now using `docker build -t getting-started .` again. This time, your output should look a little different.
```plaintext
Sending build context to Docker daemon 219.1kB
@@ -214,8 +214,7 @@ a change to the `package.json`. Make sense?
`Using cache`. So, hooray! We're using the build cache. Pushing and pulling this image and updates to it
will be much faster as well. Hooray!
-
-## Multi-Stage Builds
+## Multi-stage builds
While we're not going to dive into it too much in this tutorial, multi-stage builds are an incredibly powerful
tool to help use multiple stages to create an image. There are several advantages for them:
@@ -223,7 +222,7 @@ tool to help use multiple stages to create an image. There are several advantage
- Separate build-time dependencies from runtime dependencies
- Reduce overall image size by shipping _only_ what your app needs to run
-### Maven/Tomcat Example
+### Maven/Tomcat example
When building Java-based applications, a JDK is needed to compile the source code to Java bytecode. However,
that JDK isn't needed in production. Also, you might be using tools like Maven or Gradle to help build the app.
@@ -243,8 +242,7 @@ In this example, we use one stage (called `build`) to perform the actual Java bu
stage (starting at `FROM tomcat`), we copy in files from the `build` stage. The final image is only the last stage
being created (which can be overridden using the `--target` flag).
-
-### React Example
+### React example
When building React applications, we need a Node environment to compile the JS code (typically JSX), SASS stylesheets,
and more into static HTML, JS, and CSS. If we aren't doing server-side rendering, we don't even need a Node environment
@@ -266,7 +264,6 @@ COPY --from=build /app/build /usr/share/nginx/html
Here, we are using a `node:12` image to perform the build (maximizing layer caching) and then copying the output
into an nginx container. Cool, huh?
-
## Recap
By understanding a little bit about how images are structured, we can build images faster and ship fewer changes.
diff --git a/get-started/11_what_next.md b/get-started/11_what_next.md
index 5628dc634e..19d2ce5b85 100644
--- a/get-started/11_what_next.md
+++ b/get-started/11_what_next.md
@@ -7,7 +7,7 @@ description: Making sure you have more ideas of what you could do next with your
Although we're done with our workshop, there's still a LOT more to learn about containers!
We're not going to go deep-dive here, but here are a few other areas to look at next!
-## Container Orchestration
+## Container orchestration
Running containers in production is tough. You don't want to log into a machine and simply run a
`docker run` or `docker-compose up`. Why not? Well, what happens if the containers die? How do you
@@ -19,12 +19,11 @@ The general idea is that you have "managers" who receive **expected state**. Thi
machines in the cluster and delegate work to "worker" nodes. The managers watch for changes (such as
a container quitting) and then work to make **actual state** reflect the expected state.
-
-## Cloud Native Computing Foundation Projects
+## Cloud Native Computing Foundation projects
The CNCF is a vendor-neutral home for various open-source projects, including Kubernetes, Prometheus,
-Envoy, Linkerd, NATS, and more! You can view the [graduated and incubated projects here](https://www.cncf.io/projects/)
-and the entire [CNCF Landscape here](https://landscape.cncf.io/). There are a LOT of projects to help
+Envoy, Linkerd, NATS, and more! You can view the [graduated and incubated projects here](https://www.cncf.io/projects/){:target="_blank" rel="noopener" class="_"}
+and the entire [CNCF Landscape here](https://landscape.cncf.io/){:target="_blank" rel="noopener" class="_"}. There are a LOT of projects to help
solve problems around monitoring, logging, security, image registries, messaging, and more!
So, if you're new to the container landscape and cloud-native application development, welcome! Please
diff --git a/get-started/index.md b/get-started/index.md
index cf788c9900..efdd43a96d 100644
--- a/get-started/index.md
+++ b/get-started/index.md
@@ -60,7 +60,7 @@ Welcome! We are excited that you want to learn Docker.
This page contains step-by-step instructions on how to get started with Docker.
-If you are looking for information on how to containerize an application using your favorite language, see [Language-specific getting started guides](/language).
+If you are looking for information on how to containerize an application using your favorite language, see [Language-specific getting started guides](../language/index.md).
We also recommend the video walkthrough from DockerCon 2020.
@@ -68,6 +68,16 @@ We also recommend the video walkthrough from DockerCon 2020.
In this tutorial, you'll learn about creating and deploying Docker apps, including using multiple containers with a database, and using Docker Compose. You'll also deploy your containerized app to Azure.
+## Download Docker
+
+You can download and install Docker on multiple platforms. Choose your preferred operating system below.
+
+- [Mac](https://desktop.docker.com/mac/stable/Docker.dmg)
+
+- [Windows](https://desktop.docker.com/win/stable/Docker%20Desktop%20Installer.exe)
+
+- [Linux](../engine/install/index.md)
+
## Start the tutorial
If you've already run the command to get started with the tutorial, congratulations! If not, open a command prompt or bash window, and run the command:
@@ -89,24 +99,23 @@ You'll notice a few flags being used. Here's some more info on them:
>```
>docker run -dp 80:80 docker/getting-started
>```
->
+>
## The Docker Dashboard
Before going too far, we want to highlight the Docker Dashboard, which gives
you a quick view of the containers running on your machine. It gives you quick
access to container logs, lets you get a shell inside the container, and lets you
-easily manage container lifecycle (stop, remove, etc.).
+easily manage container lifecycle (stop, remove, etc.).
To access the dashboard, follow the instructions for either
-[Mac](https://docs.docker.com/docker-for-mac/dashboard/) or
-[Windows](https://docs.docker.com/docker-for-windows/dashboard/). If you open the dashboard
+[Mac](../../docker-for-mac/dashboard/) or
+[Windows](../../docker-for-windows/dashboard/). If you open the dashboard
now, you will see this tutorial running! The container name (`jolly_bouman` below) is a
randomly created name. So, you'll most likely have a different name.

-
## What is a container?
Now that you've run a container, what _is_ a container? Simply put, a container is
@@ -134,7 +143,7 @@ a default command to run, and other metadata.
We'll dive deeper into images later on, covering topics such as layering, best practices, and more.
> **Info**
->
+>
> If you're familiar with `chroot`, think of a container as an extended version of `chroot`. The
> filesystem is simply coming from the image. But, a container adds additional isolation not
> available when simply using chroot.
@@ -143,7 +152,7 @@ We'll dive deeper into images later on, covering topics such as layering, best p
Refer to the following topics for further documentation on all CLI commands used in this article:
-- [docker version](https://docs.docker.com/engine/reference/commandline/version/)
-- [docker run](https://docs.docker.com/engine/reference/commandline/run/)
-- [docker image](https://docs.docker.com/engine/reference/commandline/image/)
-- [docker container](https://docs.docker.com/engine/reference/commandline/container/)
+- [docker version](../engine/reference/commandline/version.md)
+- [docker run](../engine/reference/commandline/run.md)
+- [docker image](../engine/reference/commandline/image.md)
+- [docker container](../engine/reference/commandline/container.md)