mirror of https://github.com/docker/docs.git
get-started freshness (#17895)
* refresh get started guide Signed-off-by: Craig Osterhout <craig.osterhout@docker.com> Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
This commit is contained in:
parent
cddd8522b5
commit
e2ce6c5a8f
|
@ -10,15 +10,11 @@ For the rest of this guide, you'll be working with a simple todo
|
|||
list manager that runs on Node.js. If you're not familiar with Node.js,
|
||||
don't worry. This guide doesn't require any prior experience with JavaScript.
|
||||
|
||||
To complete this guide, you'll need the following:
|
||||
## Prerequisites
|
||||
|
||||
- Docker running locally. Follow the instructions to [download and install Docker](../get-docker.md).
|
||||
- A [Git client](https://git-scm.com/downloads){:target="_blank" rel="noopener" class="_"}.
|
||||
> **Note**
|
||||
>
|
||||
> If you use Windows and want to use Git Bash to run Docker commands, see [Working with Git Bash](../desktop/troubleshoot/topics.md#working-with-git-bash) for syntax differences.
|
||||
- An IDE or a text editor to edit files. Docker recommends using [Visual Studio Code](https://code.visualstudio.com/){:target="_blank" rel="noopener" class="_"}.
|
||||
- A conceptual understanding of [containers and images](../get-started/overview.md/#docker-objects).
|
||||
- You have installed the latest version of [Docker Desktop](../get-docker.md).
|
||||
- You have installed a [Git client](https://git-scm.com/downloads){:target="_blank" rel="noopener" class="_"}.
|
||||
- You have an IDE or a text editor to edit files. Docker recommends using [Visual Studio Code](https://code.visualstudio.com/){:target="_blank" rel="noopener" class="_"}.
|
||||
|
||||
## Get the app
|
||||
|
||||
|
@ -39,11 +35,11 @@ Before you can run the application, you need to get the application source code
|
|||
│ ├── spec/
|
||||
│ ├── src/
|
||||
│ └── yarn.lock
|
||||
```
|
||||
```
|
||||
|
||||
## Build the app's container image
|
||||
## Build the app's image
|
||||
|
||||
To build the [container image](../get-started/overview.md/#docker-objects){:target="_blank" rel="noopener" class="_"}, you'll need to use a `Dockerfile`. A Dockerfile is simply a text-based file with no file extension that contains a script of instructions. Docker uses this script to build a container image.
|
||||
To build the image, you'll need to use a Dockerfile. A Dockerfile is simply a text-based file with no file extension that contains a script of instructions. Docker uses this script to build a container image.
|
||||
|
||||
1. In the `getting-started-app` directory, the same location as the `package.json` file, create a file named `Dockerfile`. You can use the following commands to create a Dockerfile based on your operating system.
|
||||
|
||||
|
@ -54,7 +50,7 @@ To build the [container image](../get-started/overview.md/#docker-objects){:targ
|
|||
<div class="tab-content">
|
||||
<div id="mac-linux" class="tab-pane fade in active" markdown="1">
|
||||
|
||||
In the terminal, run the following commands listed below.
|
||||
In the terminal, run the following commands.
|
||||
|
||||
Make sure you're in the `getting-started-app` directory. Replace `/path/to/getting-started-app` with the path to your `getting-started-app` directory.
|
||||
```console
|
||||
|
@ -69,7 +65,7 @@ To build the [container image](../get-started/overview.md/#docker-objects){:targ
|
|||
</div>
|
||||
<div id="windows" class="tab-pane fade" markdown="1">
|
||||
|
||||
In the Windows Command Prompt, run the following commands listed below.
|
||||
In the Windows Command Prompt, run the following commands.
|
||||
|
||||
Make sure you're in the `getting-started-app` directory. Replace `\path\to\getting-started-app` with the path to your `getting-started-app` directory.
|
||||
```console
|
||||
|
@ -95,11 +91,8 @@ To build the [container image](../get-started/overview.md/#docker-objects){:targ
|
|||
CMD ["node", "src/index.js"]
|
||||
EXPOSE 3000
|
||||
```
|
||||
> **Note**
|
||||
>
|
||||
> Select an instruction in the Dockerfile example to learn more about the instruction.
|
||||
|
||||
3. Build the container image using the following commands:
|
||||
3. Build the image using the following commands:
|
||||
|
||||
In the terminal, make sure you're in the `getting-started-app` directory. Replace `/path/to/getting-started-app` with the path to your `getting-started-app` directory.
|
||||
|
||||
|
@ -107,24 +100,24 @@ To build the [container image](../get-started/overview.md/#docker-objects){:targ
|
|||
$ cd /path/to/getting-started-app
|
||||
```
|
||||
|
||||
Build the container image.
|
||||
Build the image.
|
||||
```console
|
||||
$ docker build -t getting-started .
|
||||
```
|
||||
|
||||
The `docker build` command uses the Dockerfile to build a new container image. You might have noticed that Docker downloaded a lot of "layers". This is because you instructed the builder that you wanted to start from the `node:18-alpine` image. But, since you didn't have that on your machine, Docker needed to download the image.
|
||||
The `docker build` command uses the Dockerfile to build a new image. You might have noticed that Docker downloaded a lot of "layers". This is because you instructed the builder that you wanted to start from the `node:18-alpine` image. But, since you didn't have that on your machine, Docker needed to download the image.
|
||||
|
||||
After Docker downloaded the image, the instructions from the Dockerfile copied in your application and used `yarn` to install your application's dependencies. The `CMD` directive specifies the default command to run when starting a container from this image.
|
||||
|
||||
Finally, the `-t` flag tags your image. Think of this simply as a human-readable name for the final image. Since you named the image `getting-started`, you can refer to that image when you run a container.
|
||||
Finally, the `-t` flag tags your image. Think of this as a human-readable name for the final image. Since you named the image `getting-started`, you can refer to that image when you run a container.
|
||||
|
||||
The `.` at the end of the `docker build` command tells Docker that it should look for the `Dockerfile` in the current directory.
|
||||
|
||||
## Start an app container
|
||||
|
||||
Now that you have an image, you can run the application in a [container](../get-started/overview.md/#docker-objects){:target="_blank" rel="noopener" class="_"}. To do so, you will use the `docker run` command.
|
||||
Now that you have an image, you can run the application in a container using the `docker run` command.
|
||||
|
||||
1. Start your container using the `docker run` command and specify the name of the image you just created:
|
||||
1. Run your container using the `docker run` command and specify the name of the image you just created:
|
||||
|
||||
```console
|
||||
$ docker run -dp 127.0.0.1:3000:3000 getting-started
|
||||
|
@ -134,7 +127,7 @@ Now that you have an image, you can run the application in a [container](../get-
|
|||
The `-p` flag (short for `--publish`) creates a port mapping between the host and the container.
|
||||
The `-p` flag takes a string value in the format of `HOST:CONTAINER`,
|
||||
where `HOST` is the address on the host, and `CONTAINER` is the port on the container.
|
||||
The command shown here publishes the container's port 3000 to `127.0.0.1:3000` (`localhost:3000`) on the host.
|
||||
The command publishes the container's port 3000 to `127.0.0.1:3000` (`localhost:3000`) on the host.
|
||||
Without the port mapping, you wouldn't be able to access the application from the host.
|
||||
|
||||
2. After a few seconds, open your web browser to [http://localhost:3000](http://localhost:3000){:target="_blank" rel="noopener" class="_"}.
|
||||
|
@ -143,12 +136,12 @@ Now that you have an image, you can run the application in a [container](../get-
|
|||
{: style="width:450px;margin-top:20px;"}
|
||||
{: .text-center }
|
||||
|
||||
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 them. Your frontend is successfully storing items in the backend.
|
||||
3. Add an item or two and see that it works as you expect. You can mark items as complete and remove them. Your frontend is successfully storing items in the backend.
|
||||
|
||||
|
||||
At this point, you should have a running todo list manager with a few items, all built by you.
|
||||
At this point, you have a running todo list manager with a few items.
|
||||
|
||||
If you take a quick look at your containers, you should see at least one container running that is using the `getting-started` image and on port `3000`. To see your containers, you can use the CLI or Docker Desktop's graphical interface.
|
||||
If you take a quick look at your containers, you should see at least one container running that's using the `getting-started` image and on port `3000`. To see your containers, you can use the CLI or Docker Desktop's graphical interface.
|
||||
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a data-toggle="tab" data-target="#cli">CLI</a></li>
|
||||
|
@ -180,9 +173,17 @@ In Docker Desktop, select the **Containers** tab to see a list of your container
|
|||
</div>
|
||||
</div>
|
||||
|
||||
## Next steps
|
||||
## Summary
|
||||
|
||||
In this short section, you learned the basics about creating a Dockerfile to build a container image. Once you built an image, you started a container and saw the running app.
|
||||
In this section, you learned the basics about creating a Dockerfile to build an image. Once you built an image, you started a container and saw the running app.
|
||||
|
||||
Related information:
|
||||
|
||||
- [Dockerfile reference](../engine/reference/builder.md)
|
||||
- [docker CLI reference](/engine/reference/commandline/cli/)
|
||||
- [Build with Docker guide](../build/guide/index.md)
|
||||
|
||||
## Next steps
|
||||
|
||||
Next, you're going to make a modification to your app and learn how to update your running application with a new image. Along the way, you'll learn a few other useful commands.
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
title: "Update the application"
|
||||
keywords: get started, setup, orientation, quickstart, intro, concepts, containers, docker desktop
|
||||
description: Making changes to our example learning application
|
||||
description: Making changes to your application
|
||||
---
|
||||
|
||||
In [part 2](./02_our_app.md), you containerized a todo application. In this part, you will update the application and container image. You will also learn how to stop and remove a container.
|
||||
In [part 2](./02_our_app.md), you containerized a todo application. In this part, you'll update the application and image. You'll also learn how to stop and remove a container.
|
||||
|
||||
## Update the source code
|
||||
|
||||
In the steps below, you will change the "empty text" when you don't have any todo list items to "You have no todo items yet! Add one above!"
|
||||
In the following steps, you'll change the "empty text" when you don't have any todo list items to "You have no todo items yet! Add one above!"
|
||||
|
||||
|
||||
1. In the `src/static/js/app.js` file, update line 56 to use the new empty text.
|
||||
|
@ -18,19 +18,19 @@ In the steps below, you will change the "empty text" when you don't have any tod
|
|||
+ <p className="text-center">You have no todo items yet! Add one above!</p>
|
||||
```
|
||||
|
||||
2. Build your updated version of the image, using the same `docker build` command you used in [part 2](./02_our_app.md/#build-the-apps-container-image){:target="_blank" rel="noopener" class="_"}.
|
||||
2. Build your updated version of the image, using the `docker build` command.
|
||||
|
||||
```console
|
||||
$ docker build -t getting-started .
|
||||
```
|
||||
```console
|
||||
$ docker build -t getting-started .
|
||||
```
|
||||
|
||||
3. Start a new container using the updated code.
|
||||
|
||||
```console
|
||||
$ docker run -dp 127.0.0.1:3000:3000 getting-started
|
||||
```
|
||||
```console
|
||||
$ docker run -dp 127.0.0.1:3000:3000 getting-started
|
||||
```
|
||||
|
||||
You probably saw an error like this (the IDs will be different):
|
||||
You probably saw an error like this:
|
||||
|
||||
```console
|
||||
docker: Error response from daemon: driver failed programming external connectivity on endpoint laughing_burnell
|
||||
|
@ -54,21 +54,21 @@ To remove a container, you first need to stop it. Once it has stopped, you can r
|
|||
|
||||
1. Get the ID of the container by using the `docker ps` command.
|
||||
|
||||
```console
|
||||
$ docker ps
|
||||
```
|
||||
```console
|
||||
$ docker ps
|
||||
```
|
||||
|
||||
2. Use the `docker stop` command to stop the container. Replace <the-container-id> with the ID from `docker ps`.
|
||||
2. Use the `docker stop` command to stop the container. Replace `<the-container-id>` with the ID from `docker ps`.
|
||||
|
||||
```console
|
||||
$ docker stop <the-container-id>
|
||||
```
|
||||
```console
|
||||
$ docker stop <the-container-id>
|
||||
```
|
||||
|
||||
3. Once the container has stopped, you can remove it by using the `docker rm` command.
|
||||
|
||||
```console
|
||||
$ docker rm <the-container-id>
|
||||
```
|
||||
```console
|
||||
$ docker rm <the-container-id>
|
||||
```
|
||||
|
||||
>**Note**
|
||||
>
|
||||
|
@ -81,7 +81,7 @@ To remove a container, you first need to stop it. Once it has stopped, you can r
|
|||
### Remove a container using Docker Desktop
|
||||
|
||||
1. Open Docker Desktop to the **Containers** view.
|
||||
2. Select the trash can icon under the **Actions** column for the old, currently running container that you want to delete.
|
||||
2. Select the trash can icon under the **Actions** column for the container that you want to delete.
|
||||
3. In the confirmation dialog, select **Delete forever**.
|
||||
|
||||
<hr>
|
||||
|
@ -92,24 +92,21 @@ To remove a container, you first need to stop it. Once it has stopped, you can r
|
|||
|
||||
1. Now, start your updated app using the `docker run` command.
|
||||
|
||||
```console
|
||||
$ docker run -dp 127.0.0.1:3000:3000 getting-started
|
||||
```
|
||||
```console
|
||||
$ docker run -dp 127.0.0.1:3000:3000 getting-started
|
||||
```
|
||||
|
||||
2. Refresh your browser on [http://localhost:3000](http://localhost:3000){:target="_blank" rel="noopener" class="_"} and you should see your updated help text.
|
||||
|
||||
{: style="width:55%" }
|
||||
{: .text-center }
|
||||
## Summary
|
||||
|
||||
In this section, you learned how to update and rebuild a container, as well as how to stop and remove a container.
|
||||
|
||||
Related information:
|
||||
- [docker CLI reference](/engine/reference/commandline/cli/)
|
||||
|
||||
## Next steps
|
||||
|
||||
While you were able to build an update, there were two things you might have noticed:
|
||||
Next, you'll learn how to share images with others.
|
||||
|
||||
- All of the existing items in your todo list are gone! That's not a very good app! You'll fix that
|
||||
shortly.
|
||||
- There were a lot of steps involved for such a small change. In an upcoming section, you'll learn
|
||||
how to see code updates without needing to rebuild and start a new container every time you make a change.
|
||||
|
||||
Before talking about persistence, you'll see how to share these images with others.
|
||||
|
||||
[Share the application](04_sharing_app.md){: .button .primary-btn}
|
||||
[Share the application](04_sharing_app.md){: .button .primary-btn}
|
|
@ -11,9 +11,9 @@ registry. The default registry is Docker Hub and is where all of the images you'
|
|||
|
||||
> **Docker ID**
|
||||
>
|
||||
> A Docker ID allows you to access Docker Hub which is the world's largest library and community for container images. Create a [Docker ID](https://hub.docker.com/signup){:target="_blank" rel="noopener" class="_"} for free if you don't have one.
|
||||
> A Docker ID lets you to access Docker Hub, which is the world's largest library and community for container images. Create a [Docker ID](https://hub.docker.com/signup){:target="_blank" rel="noopener" class="_"} for free if you don't have one.
|
||||
|
||||
## Create a repo
|
||||
## Create a repository
|
||||
|
||||
To push an image, you first need to create a repository on Docker Hub.
|
||||
|
||||
|
@ -21,53 +21,46 @@ To push an image, you first need to create a repository on Docker Hub.
|
|||
|
||||
2. Select the **Create Repository** button.
|
||||
|
||||
3. For the repo name, use `getting-started`. Make sure the Visibility is `Public`.
|
||||
3. For the repository name, use `getting-started`. Make sure the **Visibility** is **Public**.
|
||||
|
||||
> **Private repositories**
|
||||
>
|
||||
> Did you know that Docker offers private repositories which allows you to restrict content to specific users or teams? Check out the details on the [Docker pricing](https://www.docker.com/pricing?utm_source=docker&utm_medium=webreferral&utm_campaign=docs_driven_upgrade){:target="_blank" rel="noopener" class="_"} page.
|
||||
4. Select **Create**.
|
||||
|
||||
4. Select the **Create** button.
|
||||
|
||||
If you look at the image below an example Docker command can be seen. This command will push to this repo.
|
||||
In the following image, you can see an example Docker command from Docker Hub. This command will push to this repository.
|
||||
|
||||
{: style=width:75% }
|
||||
{: .text-center }
|
||||
|
||||
## 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".
|
||||
1. In the command line, run the `docker push` command that you see on Docker
|
||||
Hub. Note that your command will have your Docker ID, not "docker".
|
||||
|
||||
```plaintext
|
||||
$ docker push docker/getting-started
|
||||
The push refers to repository [docker.io/docker/getting-started]
|
||||
An image does not exist locally with the tag: docker/getting-started
|
||||
```
|
||||
```console
|
||||
$ docker push docker/getting-started
|
||||
The push refers to repository [docker.io/docker/getting-started]
|
||||
An image does not exist locally with the tag: docker/getting-started
|
||||
```
|
||||
|
||||
Why did it fail? The push command was looking for an image named docker/getting-started, but
|
||||
Why did it fail? The push command was looking for an image named `docker/getting-started`, but
|
||||
didn't find one. If you run `docker image ls`, you won't see one either.
|
||||
|
||||
To fix this, you need to "tag" your existing image you've built to give it another name.
|
||||
To fix this, you need to tag your existing image you've built to give it another name.
|
||||
|
||||
2. Login to the Docker Hub using the command `docker login -u YOUR-USER-NAME`.
|
||||
2. Sign in to Docker Hub using the command `docker login -u YOUR-USER-NAME`.
|
||||
|
||||
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.
|
||||
3. Use the `docker tag` command to give the `getting-started` image a new name. Replace `YOUR-USER-NAME` with your Docker ID.
|
||||
|
||||
```console
|
||||
$ docker tag getting-started YOUR-USER-NAME/getting-started
|
||||
```
|
||||
```console
|
||||
$ docker tag getting-started YOUR-USER-NAME/getting-started
|
||||
```
|
||||
|
||||
To learn more about the `docker tag` command, see [docker tag](../engine/reference/commandline/tag.md).
|
||||
4. Now run the `docker push` command again. If you're copying the value from
|
||||
Docker Hub, you can drop the `tagname` part, as you didn't add a tag to the
|
||||
image name. If you don't specify a tag, Docker uses a tag called `latest`.
|
||||
|
||||
4. Now try your push command again. If you're copying the value from Docker Hub, you can drop the
|
||||
`tagname` portion, as you didn't add a tag to the image name. If you don't specify a tag, Docker
|
||||
will use a tag called `latest`.
|
||||
|
||||
```console
|
||||
$ docker push YOUR-USER-NAME/getting-started
|
||||
```
|
||||
```console
|
||||
$ docker push YOUR-USER-NAME/getting-started
|
||||
```
|
||||
|
||||
## Run the image on a new instance
|
||||
|
||||
|
@ -90,17 +83,17 @@ new instance that has never seen this container image. To do this, you will use
|
|||
|
||||
2. Select **Login** and then select **docker** from the drop-down list.
|
||||
|
||||
3. Connect with your Docker Hub account.
|
||||
3. Sign in with your Docker Hub account and then select **Start**.
|
||||
|
||||
4. Once you're logged in, select the **ADD NEW INSTANCE** option on the left side bar. If you don't see it, make your browser a little wider. After a few seconds, a terminal window opens in your browser.
|
||||
4. Select the **ADD NEW INSTANCE** option on the left side bar. If you don't see it, make your browser a little wider. After a few seconds, a terminal window opens in your browser.
|
||||
|
||||
{: style=width:75% }
|
||||
|
||||
5. In the terminal, start your freshly pushed app.
|
||||
|
||||
```console
|
||||
$ docker run -dp 0.0.0.0:3000:3000 YOUR-USER-NAME/getting-started
|
||||
```
|
||||
```console
|
||||
$ docker run -dp 0.0.0.0:3000:3000 YOUR-USER-NAME/getting-started
|
||||
```
|
||||
|
||||
You should see the image get pulled down and eventually start up.
|
||||
|
||||
|
@ -118,19 +111,26 @@ new instance that has never seen this container image. To do this, you will use
|
|||
> [Networking](../network/index.md#published-ports).
|
||||
{: .tip }
|
||||
|
||||
6. Select on the 3000 badge when it comes up and you should see the app with your modifications.
|
||||
If the 3000 badge doesn't show up, you can select on the **Open Port** button and type in 3000.
|
||||
6. Select the 3000 badge when it appears.
|
||||
|
||||
If the 3000 badge doesn't appear, you can select **Open Port** and specify `3000`.
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you learned how to share your images by pushing them to a
|
||||
registry. You then went to a brand new instance and were able to run the freshly
|
||||
pushed image. This is quite common in CI pipelines, where the pipeline will
|
||||
create the image and push it to a registry and then the production environment
|
||||
can use the latest version of the image.
|
||||
|
||||
Related information:
|
||||
|
||||
- [docker CLI reference](/engine/reference/commandline/cli/)
|
||||
- [Multi-platform images](../build/building/multi-platform.md)
|
||||
- [Docker Hub overview](../docker-hub/index.md)
|
||||
|
||||
## Next steps
|
||||
|
||||
In this section, you learned how to share your images by pushing them to a registry. You then went to a
|
||||
brand new instance and were able to run the freshly pushed image. This is quite common in CI pipelines,
|
||||
where the pipeline will create the image and push it to a registry and then the production environment
|
||||
can use the latest version of the image.
|
||||
|
||||
Now you can circle back around to what you noticed at the end of the last
|
||||
section. As a reminder, you noticed that when you restarted the app, you lost all of your todo list items.
|
||||
That's obviously not a great user experience, so next you'll learn how you can persist the data across restarts.
|
||||
In the next section, you'll learn how to persist data in your containerized application.
|
||||
|
||||
[Persist the DB](05_persisting_data.md){: .button .primary-btn}
|
||||
|
|
|
@ -18,6 +18,10 @@ changes won't be seen in another container, even if they're using the same image
|
|||
To see this in action, you'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.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> If you use Windows and want to use Git Bash to run Docker commands, see [Working with Git Bash](../desktop/troubleshoot/topics.md#working-with-git-bash) for syntax differences.
|
||||
|
||||
1. Start an `ubuntu` container that will create a file named `/data.txt` with a random number
|
||||
between 1 and 10000.
|
||||
|
||||
|
@ -169,7 +173,7 @@ You can create the volume and start the container using the CLI or Docker Deskto
|
|||
|
||||
2. Stop and remove the container for the todo app. Use Docker Desktop or `docker ps` to get the ID and then `docker rm -f <id>` to remove it.
|
||||
|
||||
3. Start a new container using the same steps from above.
|
||||
3. Start a new container using the previous steps.
|
||||
|
||||
4. Open the app. You should see your items still in your list.
|
||||
|
||||
|
@ -198,19 +202,19 @@ $ docker volume inspect todo-db
|
|||
```
|
||||
|
||||
The `Mountpoint` is the actual location of the data on the disk. 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.
|
||||
need to have root access to access this directory from the host.
|
||||
|
||||
> **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 mount point directory, you would need to look inside of
|
||||
> that VM.
|
||||
## Summary
|
||||
|
||||
In this section, you learned how to persist container data.
|
||||
|
||||
Related information:
|
||||
|
||||
- [docker CLI reference](/engine/reference/commandline/cli/)
|
||||
- [Volumes](../storage/volumes.md)
|
||||
|
||||
## Next steps
|
||||
|
||||
At this point, you have a functioning application that can survive restarts.
|
||||
|
||||
However, you saw earlier that rebuilding images for every change takes quite a bit of time. There's got to be a better
|
||||
way to make changes, right? With bind mounts, there is a better way.
|
||||
Next, you'll learn how you can develop your app more efficiently using bind mounts.
|
||||
|
||||
[Use bind mounts](06_bind_mounts.md){: .button .primary-btn}
|
||||
|
|
|
@ -41,6 +41,10 @@ Before looking at how you can use bind mounts for developing your application,
|
|||
you can run a quick experiment to get a practical understanding of how bind mounts
|
||||
work.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> If you use Windows and want to use Git Bash to run Docker commands, see [Working with Git Bash](../desktop/troubleshoot/topics.md#working-with-git-bash) for syntax differences.
|
||||
|
||||
1. Open a terminal and change directory to the `getting-started-app`
|
||||
directory.
|
||||
|
||||
|
@ -309,14 +313,19 @@ Update your app on your host machine and see the changes reflected in the contai
|
|||
$ docker build -t getting-started .
|
||||
```
|
||||
|
||||
## Next steps
|
||||
## Summary
|
||||
|
||||
At this point, you can persist your database and see changes in your app as you develop without rebuilding the image.
|
||||
|
||||
In addition to volume mounts and bind mounts, Docker also supports other mount
|
||||
types and storage drivers for handling more complex and specialized use cases.
|
||||
To learn more about the advanced storage concepts, see
|
||||
[Manage data in Docker](https://docs.docker.com/storage/).
|
||||
|
||||
Related information:
|
||||
|
||||
- [docker CLI reference](/engine/reference/commandline/cli/)
|
||||
- [Manage data in Docker](https://docs.docker.com/storage/)
|
||||
|
||||
## Next steps
|
||||
|
||||
In order to prepare your app for production, you need to migrate your database
|
||||
from working in SQLite to something that can scale a little better. For
|
||||
|
@ -325,3 +334,4 @@ to use MySQL. But, how should you run MySQL? How do you allow the containers to
|
|||
talk to each other? You'll learn about that in the next section.
|
||||
|
||||
[Multi container apps](07_multi_container.md){: .button .primary-btn}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ In the following steps, you'll create the network first and then attach the MySQ
|
|||
</div>
|
||||
</div>
|
||||
|
||||
In the command above, you'll see the `--network-alias` flag. In a later section, you'll learn more about this flag.
|
||||
In the previous command, you can see the `--network-alias` flag. In a later section, you'll learn more about this flag.
|
||||
|
||||
> **Tip**
|
||||
>
|
||||
|
@ -195,7 +195,7 @@ The todo app supports the setting of a few environment variables to specify MySQ
|
|||
|
||||
You can now start your dev-ready container.
|
||||
|
||||
1. Specify each of the environment variables above, as well as connect the container to your app network. Make sure that you are in the `getting-started-app` directory when you run this command.
|
||||
1. Specify each of the previous environment variables, as well as connect the container to your app network. Make sure that you are in the `getting-started-app` directory when you run this command.
|
||||
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a data-toggle="tab" data-target="#mac-linux2">Mac / Linux</a></li>
|
||||
|
@ -273,14 +273,20 @@ You can now start your dev-ready container.
|
|||
|
||||
Your table will look different because it has your items. But, you should see them stored there.
|
||||
|
||||
## Next steps
|
||||
## Summary
|
||||
|
||||
At this point, you have an application that now stores its data in an external database running in a separate
|
||||
container. You learned a little bit about container networking and service discovery using DNS.
|
||||
|
||||
But, there's a good chance you are starting to feel a little overwhelmed with everything you need to do to start up
|
||||
Related information:
|
||||
- [docker CLI reference](/engine/reference/commandline/cli/)
|
||||
- [Networking overview](../network/index.md)
|
||||
|
||||
## Next steps
|
||||
|
||||
There's a good chance you are starting to feel a little overwhelmed with everything you need to do to start up
|
||||
this application. You have to create a network, start containers, specify all of the environment variables, expose
|
||||
ports, and more! That's a lot to remember and it's certainly making things harder to pass along to someone else.
|
||||
ports, and more. That's a lot to remember and it's certainly making things harder to pass along to someone else.
|
||||
|
||||
In the next section, you'll learn about Docker Compose. With Docker Compose, you can share your application stacks in a
|
||||
much easier way and let others spin them up with a single, simple command.
|
||||
|
|
|
@ -1,48 +1,36 @@
|
|||
---
|
||||
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
|
||||
description: Using Docker Compose for multi-container applications
|
||||
---
|
||||
|
||||
[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.
|
||||
[Docker Compose](../compose/index.md) is a tool that helps you define and
|
||||
share multi-container applications. With Compose, you can create a YAML file to define the services
|
||||
and with a single command, you can spin everything up or tear it all down.
|
||||
|
||||
The _big_ advantage of using Compose is you can define your application stack in a file, keep it at the root of
|
||||
your project repo (it's now version controlled), and easily enable someone else to contribute to your project.
|
||||
Someone would only need to clone your repo and start the compose app. In fact, you might see quite a few projects
|
||||
The big advantage of using Compose is you can define your application stack in a file, keep it at the root of
|
||||
your project repository (it's now version controlled), and easily enable someone else to contribute to your project.
|
||||
Someone would only need to clone your repository and start the app using Compose. In fact, you might see quite a few projects
|
||||
on GitHub/GitLab doing exactly this now.
|
||||
|
||||
So, how do we get started?
|
||||
|
||||
## Install Docker Compose
|
||||
|
||||
If you installed Docker Desktop for Windows, Mac, or Linux you already have Docker Compose!
|
||||
Play-with-Docker instances already have Docker Compose installed as well.
|
||||
|
||||
Standalone installations of Docker Engine requires Docker Compose to be installed as a separate package, see [Install the Compose plugin](../compose/install/linux.md).
|
||||
|
||||
After installation, you should be able to run the following and see version information.
|
||||
|
||||
```console
|
||||
$ docker compose version
|
||||
```
|
||||
|
||||
## Create the Compose file
|
||||
|
||||
1. At the root of the `/getting-started-app` folder, create a file named `docker-compose.yml`.
|
||||
In the `getting-started-app` directory, create a file named `compose.yaml`.
|
||||
|
||||
2. In the compose file, we'll start off by defining the list of services (or containers) we want to run as part of our application.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
```
|
||||
|
||||
And now, we'll start migrating a service at a time into the compose file.
|
||||
├── getting-started-app/
|
||||
│ ├── Dockerfile
|
||||
│ ├── compose.yaml
|
||||
│ ├── node_modules/
|
||||
│ ├── package.json
|
||||
│ ├── spec/
|
||||
│ ├── src/
|
||||
│ └── yarn.lock
|
||||
```
|
||||
|
||||
## Define the app service
|
||||
|
||||
To remember, this was the command we were using to define our app container.
|
||||
In [part 7](./07_multi_container.md), you used the following command to start the database service.
|
||||
|
||||
```console
|
||||
$ docker run -dp 127.0.0.1:3000:3000 \
|
||||
|
@ -56,8 +44,10 @@ $ docker run -dp 127.0.0.1:3000:3000 \
|
|||
sh -c "yarn install && yarn run dev"
|
||||
```
|
||||
|
||||
1. First, let's define the service entry and the image for the container. We can pick any name for the service.
|
||||
The name will automatically become a network alias, which will be useful when defining our MySQL service.
|
||||
You'll now define this service in the `compose.yaml` file.
|
||||
|
||||
1. Open `compose.yaml` in a text or code editor, and start by defining the name and image of the first service (or container) you want to run as part of your application.
|
||||
The name will automatically become a network alias, which will be useful when defining your MySQL service.
|
||||
|
||||
```yaml
|
||||
|
||||
|
@ -66,8 +56,7 @@ $ docker run -dp 127.0.0.1:3000:3000 \
|
|||
image: node:18-alpine
|
||||
```
|
||||
|
||||
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.
|
||||
2. Typically, you will see `command` close to the `image` definition, although there is no requirement on ordering. Add the `command` to your `compose.yaml` file.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
|
@ -76,10 +65,7 @@ $ docker run -dp 127.0.0.1:3000:3000 \
|
|||
command: sh -c "yarn install && yarn run dev"
|
||||
```
|
||||
|
||||
|
||||
3. Let's migrate the `-p 127.0.0.1:3000:3000` part of the command by defining the `ports` for the service. We will use the
|
||||
[short syntax](../compose/compose-file/05-services.md#short-syntax-3) here, but there is also a more verbose
|
||||
[long syntax](../compose/compose-file/05-services.md#long-syntax-3) available as well.
|
||||
3. Now migrate the `-p 127.0.0.1:3000:3000` part of the command by defining the `ports` for the service.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
|
@ -89,11 +75,11 @@ $ docker run -dp 127.0.0.1:3000:3000 \
|
|||
ports:
|
||||
- 127.0.0.1:3000:3000
|
||||
```
|
||||
|
||||
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/05-services.md#short-syntax-5) and [long](../compose/compose-file/05-services.md#long-syntax-5) syntax.
|
||||
|
||||
One advantage of Docker Compose volume definitions is we can use relative paths from the current directory.
|
||||
4. Next, migrate both the working directory (`-w /app`) and the volume mapping
|
||||
(`-v "$(pwd):/app"`) by using the `working_dir` and `volumes` definitions.
|
||||
|
||||
One advantage of Docker Compose volume definitions is you can use relative paths from the current directory.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
|
@ -107,7 +93,7 @@ $ docker run -dp 127.0.0.1:3000:3000 \
|
|||
- ./:/app
|
||||
```
|
||||
|
||||
5. Finally, we need to migrate the environment variable definitions using the `environment` key.
|
||||
5. Finally, you need to migrate the environment variable definitions using the `environment` key.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
|
@ -128,7 +114,7 @@ $ docker run -dp 127.0.0.1:3000:3000 \
|
|||
|
||||
### Define the MySQL service
|
||||
|
||||
Now, it's time to define the MySQL service. The command that we used for that container was the following:
|
||||
Now, it's time to define the MySQL service. The command that you used for that container was the following:
|
||||
|
||||
```console
|
||||
$ docker run -d \
|
||||
|
@ -139,8 +125,7 @@ $ docker run -d \
|
|||
mysql:8.0
|
||||
```
|
||||
|
||||
1. We will first define the new service and name it `mysql` so it automatically gets the network alias. We'll
|
||||
go ahead and specify the image to use as well.
|
||||
1. First define the new service and name it `mysql` so it automatically gets the network alias. Also specify the image to use as well.
|
||||
|
||||
```yaml
|
||||
|
||||
|
@ -151,10 +136,12 @@ $ docker run -d \
|
|||
image: mysql:8.0
|
||||
```
|
||||
|
||||
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](../compose/compose-file/07-volumes.md) though.
|
||||
2. Next, define the volume mapping. When you ran the container with `docker
|
||||
run`, Docker created the named volume automatically. However, that doesn't
|
||||
happen when running with Compose. You 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.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
|
@ -169,7 +156,7 @@ $ docker run -d \
|
|||
todo-mysql-data:
|
||||
```
|
||||
|
||||
3. Finally, we only need to specify the environment variables.
|
||||
3. Finally, you need to specify the environment variables.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
|
@ -187,7 +174,7 @@ $ docker run -d \
|
|||
todo-mysql-data:
|
||||
```
|
||||
|
||||
At this point, our complete `docker-compose.yml` should look like this:
|
||||
At this point, your complete `compose.yaml` should look like this:
|
||||
|
||||
|
||||
```yaml
|
||||
|
@ -220,30 +207,30 @@ volumes:
|
|||
|
||||
## Run the application stack
|
||||
|
||||
Now that we have our `docker-compose.yml` file, we can start it up!
|
||||
Now that you have your `compose.yaml` file, you can start your application.
|
||||
|
||||
1. Make sure no other copies of the app/db are running first (`docker ps` and `docker rm -f <ids>`).
|
||||
1. Make sure no other copies of the containers are running first. Use `docker ps` to list the containers and `docker rm -f <ids>` to remove them.
|
||||
|
||||
2. Start up the application stack using the `docker compose up` command. We'll add the `-d` flag to run everything in the
|
||||
background.
|
||||
2. Start up the application stack using the `docker compose up` command. Add the
|
||||
`-d` flag to run everything in the background.
|
||||
|
||||
```console
|
||||
$ docker compose up -d
|
||||
```
|
||||
```console
|
||||
$ docker compose up -d
|
||||
```
|
||||
|
||||
When we run this, we should see output like this:
|
||||
When you run the previous command, you should see output like the following:
|
||||
|
||||
```plaintext
|
||||
Creating network "app_default" with the default driver
|
||||
Creating volume "app_todo-mysql-data" with default driver
|
||||
Creating app_app_1 ... done
|
||||
Creating app_mysql_1 ... done
|
||||
```
|
||||
```plaintext
|
||||
Creating network "app_default" with the default driver
|
||||
Creating volume "app_todo-mysql-data" with default driver
|
||||
Creating app_app_1 ... done
|
||||
Creating app_mysql_1 ... done
|
||||
```
|
||||
|
||||
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).
|
||||
You'll notice that Docker Compose created the volume as well as a network. By default, Docker Compose automatically creates a network specifically for the application stack (which is why you didn't define one in the Compose file).
|
||||
|
||||
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
|
||||
3. 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.
|
||||
|
||||
If you have run the command already, you'll see output that looks like this:
|
||||
|
@ -259,21 +246,17 @@ 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`).
|
||||
|
||||
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!
|
||||
4. At this point, you should be able to open your app in your browser on [http://localhost:3000](http://localhost:3000){:target="_blank" rel="noopener" class="_"} and see it running.
|
||||
|
||||
## 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
|
||||
If you look at the Docker Dashboard, you'll see that there is a group named **getting-started-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
|
||||
`docker-compose.yml` was located in.
|
||||
`compose.yaml` was located in.
|
||||
|
||||

|
||||
|
||||
If you click the disclose arrow next to **app**, you will see the two containers we defined in the compose file. The names are also a little
|
||||
If you expand the stack, you'll see the two containers you defined in the Compose file. The names are also a little
|
||||
more descriptive, as they follow the pattern of `<service-name>-<replica-number>`. So, it's very easy to
|
||||
quickly see what container is our app and which container is the mysql database.
|
||||
|
||||

|
||||
quickly see what container is your app and which container is the mysql database.
|
||||
|
||||
## Tear it all down
|
||||
|
||||
|
@ -282,24 +265,24 @@ for the entire app. The containers will stop and the network will be removed.
|
|||
|
||||
>**Warning**
|
||||
>
|
||||
>Removing Volumes
|
||||
>By default, named volumes in your compose file are not removed when you run `docker compose down`. If you want to
|
||||
>remove the volumes, you need to add the `--volumes` flag.
|
||||
>
|
||||
>By default, named volumes in your compose file are NOT removed when running `docker compose down`. If you want to
|
||||
>remove the volumes, you will need to add the `--volumes` flag.
|
||||
>
|
||||
>The Docker Dashboard does _not_ remove volumes when you delete the app stack.
|
||||
>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!
|
||||
## Summary
|
||||
|
||||
In this section, you learned about Docker Compose and how it helps you simplify
|
||||
the way you define and share multi-service applications.
|
||||
|
||||
Related information:
|
||||
- [Compose overview](../compose/index.md)
|
||||
- [Compose file reference](../compose/compose-file/index.md)
|
||||
- [Compose CLI reference](../compose/reference/index.md)
|
||||
|
||||
## Next steps
|
||||
|
||||
In this section, you learned about Docker Compose and how it helps you dramatically simplify the defining and
|
||||
sharing of multi-service applications. You created a Compose file by translating the commands you were
|
||||
using into the appropriate compose format.
|
||||
Next, you'll learn about a few best practices you can use to improve your Dockerfile.
|
||||
|
||||
At this point, you're starting to wrap up the tutorial. However, there are a few best practices about
|
||||
image building you should cover, as there is a big issue with the Dockerfile you've been using.
|
||||
|
||||
[Image-building best practices](09_image_best.md){: .button .primary-btn}
|
||||
[Image-building best practices](09_image_best.md){: .button .primary-btn}
|
|
@ -1,22 +1,22 @@
|
|||
---
|
||||
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
|
||||
description: Tips for building images for your application
|
||||
---
|
||||
|
||||
## 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.
|
||||
Using the `docker image history` command, you can see the command that was used
|
||||
to create each layer within an image.
|
||||
|
||||
1. Use the `docker image history` command to see the layers in the `getting-started` image you
|
||||
created earlier in the tutorial.
|
||||
created.
|
||||
|
||||
```console
|
||||
$ docker image history getting-started
|
||||
```
|
||||
|
||||
You should get output that looks something like this (dates/IDs may be different).
|
||||
You should get output that looks something like the following.
|
||||
|
||||
```plaintext
|
||||
IMAGE CREATED CREATED BY SIZE COMMENT
|
||||
|
@ -40,7 +40,7 @@ command, you can see the command that was used to create each layer within an im
|
|||
diagnose large images.
|
||||
|
||||
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?)
|
||||
full output.
|
||||
|
||||
```console
|
||||
$ docker image history --no-trunc getting-started
|
||||
|
@ -49,11 +49,9 @@ command, you can see the command that was used to create each layer within an im
|
|||
## 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.
|
||||
times for your container images. Once a layer changes, all downstream layers have to be recreated as well.
|
||||
|
||||
> Once a layer changes, all downstream layers have to be recreated as well
|
||||
|
||||
Let's look at the Dockerfile we were using one more time...
|
||||
Look at the following Dockerfile you created for the getting started app.
|
||||
|
||||
```dockerfile
|
||||
# syntax=docker/dockerfile:1
|
||||
|
@ -64,32 +62,32 @@ RUN yarn install --production
|
|||
CMD ["node", "src/index.js"]
|
||||
```
|
||||
|
||||
Going back to the image history output, we see that each command in the Dockerfile becomes a new layer in the image.
|
||||
You might remember that when we made a change to the image, the yarn dependencies had to be reinstalled. Is there a
|
||||
way to fix this? It doesn't make much sense to ship around the same dependencies every time we build, right?
|
||||
Going back to the image history output, you see that each command in the Dockerfile becomes a new layer in the image.
|
||||
You might remember that when you made a change to the image, the yarn dependencies had to be reinstalled. It doesn't make much sense to ship around the same dependencies every time you build.
|
||||
|
||||
To fix this, we need to restructure our Dockerfile to help support the caching of the dependencies. For Node-based
|
||||
applications, those dependencies are defined in the `package.json` file. So, what if we copied only that file in first,
|
||||
install the dependencies, and _then_ copy in everything else? Then, we only recreate the yarn dependencies if there was
|
||||
a change to the `package.json`. Make sense?
|
||||
To fix it, you need to restructure your Dockerfile to help support the caching
|
||||
of the dependencies. For Node-based applications, those dependencies are defined
|
||||
in the `package.json` file. You can copy only that file in first, install the
|
||||
dependencies, and then copy in everything else. Then, you only recreate the yarn
|
||||
dependencies if there was a change to the `package.json`.
|
||||
|
||||
1. Update the Dockerfile to copy in the `package.json` first, install dependencies, and then copy everything else in.
|
||||
|
||||
```dockerfile
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM node:18-alpine
|
||||
WORKDIR /app
|
||||
COPY package.json yarn.lock ./
|
||||
RUN yarn install --production
|
||||
COPY . .
|
||||
CMD ["node", "src/index.js"]
|
||||
```
|
||||
```dockerfile
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM node:18-alpine
|
||||
WORKDIR /app
|
||||
COPY package.json yarn.lock ./
|
||||
RUN yarn install --production
|
||||
COPY . .
|
||||
CMD ["node", "src/index.js"]
|
||||
```
|
||||
|
||||
2. Create a file named `.dockerignore` in the same folder as the Dockerfile with the following contents.
|
||||
|
||||
```ignore
|
||||
node_modules
|
||||
```
|
||||
```ignore
|
||||
node_modules
|
||||
```
|
||||
|
||||
`.dockerignore` files are an easy way to selectively copy only image relevant files.
|
||||
You can read more about this
|
||||
|
@ -106,7 +104,7 @@ a change to the `package.json`. Make sense?
|
|||
$ docker build -t getting-started .
|
||||
```
|
||||
|
||||
You should see output like this...
|
||||
You should see output like the following.
|
||||
|
||||
```plaintext
|
||||
[+] Building 16.1s (10/10) FINISHED
|
||||
|
@ -128,9 +126,7 @@ a change to the `package.json`. Make sense?
|
|||
=> => naming to docker.io/library/getting-started
|
||||
```
|
||||
|
||||
You'll see that all layers were rebuilt. Perfectly fine since we changed the Dockerfile quite a bit.
|
||||
|
||||
4. Now, make a change to the `src/static/index.html` file (like change the `<title>` to say "The Awesome Todo App").
|
||||
4. Now, make a change to the `src/static/index.html` file. For example, change the `<title>` to "The Awesome Todo App".
|
||||
|
||||
5. Build the Docker image now using `docker build -t getting-started .` again. This time, your output should look a little different.
|
||||
|
||||
|
@ -154,22 +150,23 @@ a change to the `package.json`. Make sense?
|
|||
=> => naming to docker.io/library/getting-started
|
||||
```
|
||||
|
||||
First off, you should notice that the build was MUCH faster! And, you'll see that several steps are using previously cached layers. So, hooray! We're using the build cache. Pushing and pulling this image and updates to it
|
||||
will be much faster as well. Hooray!
|
||||
First off, you should notice that the build was much faster. And, you'll see
|
||||
that several steps are using previously cached layers. Pushing and pulling
|
||||
this image and updates to it will be much faster as well.
|
||||
|
||||
## Multi-stage builds
|
||||
|
||||
While we're not going to dive into it too much in this tutorial, multi-stage builds are an incredibly powerful
|
||||
Multi-stage builds are an incredibly powerful
|
||||
tool to help use multiple stages to create an image. There are several advantages for them:
|
||||
|
||||
- Separate build-time dependencies from runtime dependencies
|
||||
- Reduce overall image size by shipping _only_ what your app needs to run
|
||||
- Reduce overall image size by shipping only what your app needs to run
|
||||
|
||||
### Maven/Tomcat example
|
||||
|
||||
When building Java-based applications, a JDK is needed to compile the source code to Java bytecode. However,
|
||||
When building Java-based applications, you need a JDK 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.
|
||||
Those also aren't needed in our final image. Multi-stage builds help.
|
||||
Those also aren't needed in your final image. Multi-stage builds help.
|
||||
|
||||
```dockerfile
|
||||
# syntax=docker/dockerfile:1
|
||||
|
@ -182,15 +179,15 @@ FROM tomcat
|
|||
COPY --from=build /app/target/file.war /usr/local/tomcat/webapps
|
||||
```
|
||||
|
||||
In this example, we use one stage (called `build`) to perform the actual Java build using Maven. In the second
|
||||
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).
|
||||
In this example, you use one stage (called `build`) to perform the actual Java build using Maven. In the second
|
||||
stage (starting at `FROM tomcat`), you 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
|
||||
|
||||
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
|
||||
for our production build. Why not ship the static resources in a static nginx container?
|
||||
When building React applications, you need a Node environment to compile the JS code (typically JSX), SASS stylesheets,
|
||||
and more into static HTML, JS, and CSS. If you aren't doing server-side rendering, you don't even need a Node environment
|
||||
for your production build. You can ship the static resources in a static nginx container.
|
||||
|
||||
```dockerfile
|
||||
# syntax=docker/dockerfile:1
|
||||
|
@ -206,16 +203,21 @@ FROM nginx:alpine
|
|||
COPY --from=build /app/build /usr/share/nginx/html
|
||||
```
|
||||
|
||||
Here, we are using a `node:18` image to perform the build (maximizing layer caching) and then copying the output
|
||||
into an nginx container. Cool, huh?
|
||||
In the previous Dockerfile example, it uses the `node:18` image to perform the build (maximizing layer caching) and then copyies the output
|
||||
into an nginx container.
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you learned a few image building best practices, including layer caching and multi-stage builds.
|
||||
|
||||
Related information:
|
||||
- [.dockerignore](../engine/reference/builder.md#dockerignore-file)
|
||||
- [Dockerfile reference](../engine/reference/builder.md)
|
||||
- [Build with Docker guide](../build/guide/index.md)
|
||||
- [Dockerfile best practices](../develop/develop-images/dockerfile_best-practices.md)
|
||||
|
||||
## Next steps
|
||||
|
||||
By understanding a little bit about the structure of images, you can build images faster and ship fewer changes.
|
||||
Scanning images gives you confidence that the containers you are running and distributing are secure.
|
||||
Multi-stage builds also help you reduce overall image size and increase final container security by separating
|
||||
build-time dependencies from runtime dependencies.
|
||||
|
||||
In the next section, you'll learn about additional resources you can use to continue learning about containers.
|
||||
|
||||
[What next](11_what_next.md){: .button .primary-btn}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
---
|
||||
title: "What next"
|
||||
title: "What next after getting started"
|
||||
keywords: get started, setup, orientation, quickstart, intro, concepts, containers, docker desktop
|
||||
description: Making sure you have more ideas of what you could do next with your application
|
||||
---
|
||||
|
||||
Although we're done with our get started guide, 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!
|
||||
Although you're done with the get started guide, there's still a lot more to learn about containers.
|
||||
|
||||
Here are a few other areas to look at next.
|
||||
|
||||
## Container orchestration
|
||||
|
||||
|
@ -14,24 +15,21 @@ Running containers in production is tough. You don't want to log into a machine
|
|||
scale across several machines? Container orchestration solves this problem. Tools like Kubernetes,
|
||||
Swarm, Nomad, and ECS all help solve this problem, all in slightly different ways.
|
||||
|
||||
The general idea is that you have "managers" who receive **expected state**. This state might be
|
||||
The general idea is that you have managers who receive the expected state. This state might be
|
||||
"I want to run two instances of my web app and expose port 80." The managers then look at all of the
|
||||
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.
|
||||
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 the actual state reflect the expected state.
|
||||
|
||||
## 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/){: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
|
||||
connect with the community, ask questions, and keep learning! We're excited to have you!
|
||||
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.
|
||||
|
||||
## Getting started video workshop
|
||||
|
||||
We recommend the video workshop from DockerCon 2022. Watch the video below or use the links to open the video at a particular section.
|
||||
Docker recommends watching the video workshop from DockerCon 2022. Watch the entire video or use the following links to open the video at a particular section.
|
||||
|
||||
* [Docker overview and installation](https://youtu.be/gAGEar5HQoU)
|
||||
* [Pull, run, and explore containers](https://youtu.be/gAGEar5HQoU?t=1400)
|
||||
|
@ -50,5 +48,5 @@ If you'd like to see how containers are built from scratch, Liz Rice from Aqua S
|
|||
|
||||
## Language-specific guides
|
||||
|
||||
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).
|
||||
If you are looking for information on how to containerize an application using your favorite language, see the [Language-specific guides](../language/index.md).
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: "Overview"
|
||||
title: Overview of the get started guide
|
||||
keywords: docker basics, how to start a docker container, container settings, setup docker, how to setup docker, setting up docker, docker container guide, how to get started with docker
|
||||
description: Get started with the Docker basics in this comprehensive overview, You'll learn about containers, images, and how to containerize your first application.
|
||||
redirect_from:
|
||||
|
@ -57,8 +57,6 @@ redirect_from:
|
|||
- /windows/step_two/
|
||||
---
|
||||
|
||||
Welcome! We're excited that you want to learn Docker.
|
||||
|
||||
This guide contains step-by-step instructions on how to get started with Docker. This guide shows you how to:
|
||||
|
||||
- Build and run an image as a container.
|
||||
|
@ -71,26 +69,22 @@ This guide contains step-by-step instructions on how to get started with Docker.
|
|||
A container is a sandboxed process running on a host machine that is isolated from all other processes running on that host machine. That isolation leverages [kernel namespaces and cgroups](https://medium.com/@saschagrunert/demystifying-containers-part-i-kernel-space-2c53d6979504),
|
||||
features that have been in Linux for a long time. Docker makes these capabilities approachable and easy to use. To summarize, a container:
|
||||
|
||||
- Is a runnable instance of an image. You can create, start, stop, move, or delete a container using the DockerAPI or CLI.
|
||||
- Is a runnable instance of an image. You can create, start, stop, move, or delete a container using the Docker API or CLI.
|
||||
- Can be run on local machines, virtual machines, or deployed to the cloud.
|
||||
- Is portable (and can be run on any OS).
|
||||
- Is isolated from other containers and runs its own software, binaries, configurations, etc.
|
||||
|
||||
## What is a container image?
|
||||
If you're familiar with `chroot`, then think of a container as an extended version of `chroot`. The filesystem comes from the image. However, a container adds additional isolation not available when using chroot.
|
||||
|
||||
A running container uses an isolated filesystem. This isolated filesystem is provided by a container image, and the container image must contain everything needed to run an application - all dependencies, configurations, scripts, binaries, etc. The image also contains other configurations for the container, such as environment variables, a default command to run, and other metadata.
|
||||
## What is an image?
|
||||
|
||||
This guide covers topics such as image layers, best practices, and more.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> If you're familiar with `chroot`, then think of a container as an extended version of `chroot`. The filesystem comes from the image. However, a container adds additional isolation not available when using chroot.
|
||||
A running container uses an isolated filesystem. This isolated filesystem is provided by an image, and the image must contain everything needed to run an application - all dependencies, configurations, scripts, binaries, etc. The image also contains other configurations for the container, such as environment variables, a default command to run, and other metadata.
|
||||
|
||||
## Next steps
|
||||
|
||||
In this section, we introduced containers and container images.
|
||||
In this section, you learned about containers and images.
|
||||
|
||||
Next, we containerize a simple application.
|
||||
Next, you'll containerize a simple application and get hands-on with the concepts.
|
||||
|
||||
[Containerize an application](02_our_app.md){: .button .primary-btn}
|
||||
|
||||
|
|
|
@ -14,16 +14,16 @@ Docker is an open platform for developing, shipping, and running applications.
|
|||
Docker enables you to separate your applications from your infrastructure so
|
||||
you can deliver software quickly. With Docker, you can manage your infrastructure
|
||||
in the same ways you manage your applications. By taking advantage of Docker's
|
||||
methodologies for shipping, testing, and deploying code quickly, you can
|
||||
methodologies for shipping, testing, and deploying code, you can
|
||||
significantly reduce the delay between writing code and running it in production.
|
||||
|
||||
## The Docker platform
|
||||
|
||||
Docker provides the ability to package and run an application in a loosely isolated
|
||||
environment called a container. The isolation and security allows you to run many
|
||||
environment called a container. The isolation and security lets you to run many
|
||||
containers simultaneously on a given host. Containers are lightweight and contain
|
||||
everything needed to run the application, so you do not need to rely on what is
|
||||
currently installed on the host. You can easily share containers while you work,
|
||||
everything needed to run the application, so you don't need to rely on what's
|
||||
installed on the host. You can share containers while you work,
|
||||
and be sure that everyone you share with gets the same container that works in the
|
||||
same way.
|
||||
|
||||
|
@ -38,7 +38,7 @@ Docker provides tooling and a platform to manage the lifecycle of your container
|
|||
|
||||
## What can I use Docker for?
|
||||
|
||||
**Fast, consistent delivery of your applications**
|
||||
### Fast, consistent delivery of your applications
|
||||
|
||||
Docker streamlines the development lifecycle by allowing developers to work in
|
||||
standardized environments using local containers which provide your applications
|
||||
|
@ -49,14 +49,14 @@ Consider the following example scenario:
|
|||
|
||||
- Your developers write code locally and share their work with their colleagues
|
||||
using Docker containers.
|
||||
- They use Docker to push their applications into a test environment and execute
|
||||
- They use Docker to push their applications into a test environment and run
|
||||
automated and manual tests.
|
||||
- When developers find bugs, they can fix them in the development environment
|
||||
and redeploy them to the test environment for testing and validation.
|
||||
- When testing is complete, getting the fix to the customer is as simple as
|
||||
pushing the updated image to the production environment.
|
||||
|
||||
**Responsive deployment and scaling**
|
||||
### Responsive deployment and scaling
|
||||
|
||||
Docker's container-based platform allows for highly portable workloads. Docker
|
||||
containers can run on a developer's local laptop, on physical or virtual
|
||||
|
@ -66,7 +66,7 @@ Docker's portability and lightweight nature also make it easy to dynamically
|
|||
manage workloads, scaling up or tearing down applications and services as
|
||||
business needs dictate, in near real time.
|
||||
|
||||
**Running more workloads on the same hardware**
|
||||
### Running more workloads on the same hardware
|
||||
|
||||
Docker is lightweight and fast. It provides a viable, cost-effective alternative
|
||||
to hypervisor-based virtual machines, so you can use more of your server
|
||||
|
@ -76,9 +76,9 @@ fewer resources.
|
|||
|
||||
## Docker architecture
|
||||
|
||||
Docker uses a client-server architecture. The Docker *client* talks to the
|
||||
Docker *daemon*, which does the heavy lifting of building, running, and
|
||||
distributing your Docker containers. The Docker client and daemon *can*
|
||||
Docker uses a client-server architecture. The Docker client talks to the
|
||||
Docker daemon, which does the heavy lifting of building, running, and
|
||||
distributing your Docker containers. The Docker client and daemon can
|
||||
run on the same system, or you can connect a Docker client to a remote Docker
|
||||
daemon. The Docker client and daemon communicate using a REST API, over UNIX
|
||||
sockets or a network interface. Another Docker client is Docker Compose,
|
||||
|
@ -105,13 +105,12 @@ Docker Desktop is an easy-to-install application for your Mac, Windows or Linux
|
|||
|
||||
### Docker registries
|
||||
|
||||
A Docker _registry_ stores Docker images. Docker Hub is a public
|
||||
registry that anyone can use, and Docker is configured to look for images on
|
||||
A Docker registry stores Docker images. Docker Hub is a public
|
||||
registry that anyone can use, and Docker is looks for images on
|
||||
Docker Hub by default. You can even run your own private registry.
|
||||
|
||||
When you use the `docker pull` or `docker run` commands, the required images are
|
||||
pulled from your configured registry. When you use the `docker push` command,
|
||||
your image is pushed to your configured registry.
|
||||
When you use the `docker pull` or `docker run` commands, Docker pulls the required images from your configured registry. When you use the `docker push` command, Docker pushes
|
||||
your image to your configured registry.
|
||||
|
||||
### Docker objects
|
||||
|
||||
|
@ -121,14 +120,14 @@ of those objects.
|
|||
|
||||
#### Images
|
||||
|
||||
An _image_ is a read-only template with instructions for creating a Docker
|
||||
container. Often, an image is _based on_ another image, with some additional
|
||||
An image is a read-only template with instructions for creating a Docker
|
||||
container. Often, an image is_based on another image, with some additional
|
||||
customization. For example, you may build an image which is based on the `ubuntu`
|
||||
image, but installs the Apache web server and your application, as well as the
|
||||
configuration details needed to make your application run.
|
||||
|
||||
You might create your own images or you might only use those created by others
|
||||
and published in a registry. To build your own image, you create a _Dockerfile_
|
||||
and published in a registry. To build your own image, you create a Dockerfile
|
||||
with a simple syntax for defining the steps needed to create the image and run
|
||||
it. Each instruction in a Dockerfile creates a layer in the image. When you
|
||||
change the Dockerfile and rebuild the image, only those layers which have
|
||||
|
@ -149,7 +148,7 @@ machine.
|
|||
|
||||
A container is defined by its image as well as any configuration options you
|
||||
provide to it when you create or start it. When a container is removed, any changes to
|
||||
its state that are not stored in persistent storage disappear.
|
||||
its state that aren't stored in persistent storage disappear.
|
||||
|
||||
##### Example `docker run` command
|
||||
|
||||
|
@ -163,7 +162,7 @@ $ docker run -i -t ubuntu /bin/bash
|
|||
When you run this command, the following happens (assuming you are using
|
||||
the default registry configuration):
|
||||
|
||||
1. If you do not have the `ubuntu` image locally, Docker pulls it from your
|
||||
1. If you don't have the `ubuntu` image locally, Docker pulls it from your
|
||||
configured registry, as though you had run `docker pull ubuntu` manually.
|
||||
|
||||
2. Docker creates a new container, as though you had run a `docker container create`
|
||||
|
@ -174,29 +173,29 @@ the default registry configuration):
|
|||
directories in its local filesystem.
|
||||
|
||||
4. Docker creates a network interface to connect the container to the default
|
||||
network, since you did not specify any networking options. This includes
|
||||
network, since you didn't specify any networking options. This includes
|
||||
assigning an IP address to the container. By default, containers can
|
||||
connect to external networks using the host machine's network connection.
|
||||
|
||||
5. Docker starts the container and executes `/bin/bash`. Because the container
|
||||
is running interactively and attached to your terminal (due to the `-i` and `-t`
|
||||
flags), you can provide input using your keyboard while the output is logged to
|
||||
flags), you can provide input using your keyboard while Docker logs the output to
|
||||
your terminal.
|
||||
|
||||
6. When you type `exit` to terminate the `/bin/bash` command, the container
|
||||
stops but is not removed. You can start it again or remove it.
|
||||
6. When you run `exit` to terminate the `/bin/bash` command, the container
|
||||
stops but isn't removed. You can start it again or remove it.
|
||||
|
||||
## The underlying technology
|
||||
Docker is written in the [Go programming language](https://golang.org/) and takes
|
||||
advantage of several features of the Linux kernel to deliver its functionality.
|
||||
Docker uses a technology called `namespaces` to provide the isolated workspace
|
||||
called the *container*. When you run a container, Docker creates a set of
|
||||
*namespaces* for that container.
|
||||
called the container. When you run a container, Docker creates a set of
|
||||
namespaces for that container.
|
||||
|
||||
These namespaces provide a layer of isolation. Each aspect of a container runs
|
||||
in a separate namespace and its access is limited to that namespace.
|
||||
|
||||
## Next steps
|
||||
- Read about [installing Docker](../get-docker.md).
|
||||
- Get hands-on experience with the [Getting started with Docker](index.md)
|
||||
tutorial.
|
||||
|
||||
- [Install Docker](../get-docker.md)
|
||||
- [Get started with Docker](index.md)
|
||||
|
|
Loading…
Reference in New Issue