1 Commits

Author SHA1 Message Date
Ben.Destpaer-gotch
2ef123150d Adding in VSCode alternate branch
Adding in VSCode UI elements instead of Desktop UI elements
2020-07-08 18:25:26 +02:00
27 changed files with 2779 additions and 2605 deletions

View File

@@ -1,12 +0,0 @@
name: Build
on: [push, pull_request]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
uses: docker/build-push-action@v1
with:
push: false

View File

@@ -1,28 +1,23 @@
# Install the base requirements for the app. # Install the base requirements for the app.
# This stage is to support development. # This stage is to support development.
FROM python:alpine@sha256:c9d3c11e89887c82efeb4f4fee8771a406cf42f41aebbd23148906d5fe3c1426 AS base FROM python:alpine AS base
WORKDIR /app WORKDIR /app
COPY requirements.txt . COPY requirements.txt .
RUN pip install -r requirements.txt RUN pip install -r requirements.txt
FROM node:12-alpine@sha256:d4b15b3d48f42059a15bd659be60afe21762aae9d6cbea6f124440895c27db68 AS app-base # Run tests to validate app
FROM node:12-alpine AS app-base
WORKDIR /app WORKDIR /app
COPY app/package.json app/yarn.lock ./ COPY app/package.json app/yarn.lock ./
RUN yarn install
COPY app/spec ./spec COPY app/spec ./spec
COPY app/src ./src COPY app/src ./src
# Run tests to validate app
FROM app-base AS test
RUN apk add --no-cache python3 g++ make
RUN yarn install
RUN yarn test RUN yarn test
# Clear out the node_modules and create the zip # Clear out the node_modules and create the zip
FROM app-base AS app-zip-creator FROM app-base AS app-zip-creator
COPY app/package.json app/yarn.lock ./ RUN rm -rf node_modules && \
COPY app/spec ./spec apk add zip && \
COPY app/src ./src
RUN apk add zip && \
zip -r /app.zip /app zip -r /app.zip /app
# Dev-ready container - actual files will be mounted in # Dev-ready container - actual files will be mounted in
@@ -36,6 +31,6 @@ RUN mkdocs build
# Extract the static content from the build # Extract the static content from the build
# and use a nginx image to serve the content # and use a nginx image to serve the content
FROM nginx:alpine@sha256:082f8c10bd47b6acc8ef15ae61ae45dd8fde0e9f389a8b5cb23c37408642bf5d FROM nginx:alpine
COPY --from=app-zip-creator /app.zip /usr/share/nginx/html/assets/app.zip COPY --from=app-zip-creator /app.zip /usr/share/nginx/html/assets/app.zip
COPY --from=build /app/site /usr/share/nginx/html COPY --from=build /app/site /usr/share/nginx/html

2
Jenkinsfile vendored
View File

@@ -10,7 +10,7 @@ pipeline {
when { when {
branch 'master' branch 'master'
} }
sh "docker build -t docker/getting-started ." sh "docker build docker/getting-started ."
steps { steps {
withDockerRegistry([url: "", credentialsId: "dockerbuildbot-index.docker.io"]) { withDockerRegistry([url: "", credentialsId: "dockerbuildbot-index.docker.io"]) {

View File

@@ -37,6 +37,6 @@ docker-compose up
If you find typos or other issues with the tutorial, feel free to create a PR and suggest fixes! If you find typos or other issues with the tutorial, feel free to create a PR and suggest fixes!
If you have ideas on how to make the tutorial better or new content, please open an issue first before working on your idea. While we love input, we want to keep the tutorial scoped to newcomers. If you have ideas on how to make the tutorial better or new content, please open an issue first before working on your idea. While we love input, we want to keep the tutorial is scoped to new-comers.
As such, we may reject ideas for more advanced requests and don't want you to lose any work you might As such, we may reject ideas for more advanced requests and don't want you to lose any work you might
have done. So, ask first and we'll gladly hear your thoughts! have done. So, ask first and we'll gladly hear your thoughts!

View File

@@ -9,15 +9,13 @@
"dev": "nodemon src/index.js" "dev": "nodemon src/index.js"
}, },
"dependencies": { "dependencies": {
"body-parser": "^1.19.0",
"express": "^4.17.1", "express": "^4.17.1",
"mysql": "^2.17.1", "mysql": "^2.17.1",
"sqlite3": "^5.0.0", "sqlite3": "^4.1.0",
"uuid": "^3.3.3", "uuid": "^3.3.3",
"wait-port": "^0.2.2" "wait-port": "^0.2.2"
}, },
"resolutions": {
"ansi-regex": "5.0.1"
},
"prettier": { "prettier": {
"trailingComma": "all", "trailingComma": "all",
"tabWidth": 4, "tabWidth": 4,
@@ -26,8 +24,8 @@
"singleQuote": true "singleQuote": true
}, },
"devDependencies": { "devDependencies": {
"jest": "^27.2.5", "jest": "^24.9.0",
"nodemon": "^2.0.13", "nodemon": "^1.19.2",
"prettier": "^1.18.2" "prettier": "^1.18.2"
} }
} }

View File

@@ -1,6 +1,5 @@
const db = require('../../src/persistence/sqlite'); const db = require('../../src/persistence/sqlite');
const fs = require('fs'); const fs = require('fs');
const location = process.env.SQLITE_DB_LOCATION || '/etc/todos/todo.db';
const ITEM = { const ITEM = {
id: '7aef3d7c-d301-4846-8358-2a91ec9d6be3', id: '7aef3d7c-d301-4846-8358-2a91ec9d6be3',
@@ -9,8 +8,8 @@ const ITEM = {
}; };
beforeEach(() => { beforeEach(() => {
if (fs.existsSync(location)) { if (fs.existsSync('/etc/todos/todo.db')) {
fs.unlinkSync(location); fs.unlinkSync('/etc/todos/todo.db');
} }
}); });

View File

@@ -6,7 +6,7 @@ const addItem = require('./routes/addItem');
const updateItem = require('./routes/updateItem'); const updateItem = require('./routes/updateItem');
const deleteItem = require('./routes/deleteItem'); const deleteItem = require('./routes/deleteItem');
app.use(express.json()); app.use(require('body-parser').json());
app.use(express.static(__dirname + '/static')); app.use(express.static(__dirname + '/static'));
app.get('/items', getItems); app.get('/items', getItems);

View File

@@ -29,12 +29,11 @@ async function init() {
user, user,
password, password,
database, database,
charset: 'utf8mb4',
}); });
return new Promise((acc, rej) => { return new Promise((acc, rej) => {
pool.query( pool.query(
'CREATE TABLE IF NOT EXISTS todo_items (id varchar(36), name varchar(255), completed boolean) DEFAULT CHARSET utf8mb4', 'CREATE TABLE IF NOT EXISTS todo_items (id varchar(36), name varchar(255), completed boolean)',
err => { err => {
if (err) return rej(err); if (err) return rej(err);

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,6 @@ else
fi fi
docker buildx build \ docker buildx build \
--platform linux/amd64,linux/arm64 \ --platform linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6 \
-t docker/getting-started:latest \ -t docker/getting-started:latest \
$( (( $WILL_PUSH == 1 )) && printf %s '--push' ) . $( (( $WILL_PUSH == 1 )) && printf %s '--push' ) .

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

View File

@@ -1,46 +1,3 @@
## 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.
For example, to scan the `getting-started` image you created earlier in the tutorial, you can just type
```bash
docker scan getting-started
```
The scan uses a constantly updated database of vulnerabilities, so the output you see will vary as new
vulnerabilities are discovered, but it might look something like this:
```plaintext
✗ Low severity vulnerability found in freetype/freetype
Description: CVE-2020-15999
Info: https://snyk.io/vuln/SNYK-ALPINE310-FREETYPE-1019641
Introduced through: freetype/freetype@2.10.0-r0, gd/libgd@2.2.5-r2
From: freetype/freetype@2.10.0-r0
From: gd/libgd@2.2.5-r2 > freetype/freetype@2.10.0-r0
Fixed in: 2.10.0-r1
✗ Medium severity vulnerability found in libxml2/libxml2
Description: Out-of-bounds Read
Info: https://snyk.io/vuln/SNYK-ALPINE310-LIBXML2-674791
Introduced through: libxml2/libxml2@2.9.9-r3, libxslt/libxslt@1.1.33-r3, nginx-module-xslt/nginx-module-xslt@1.17.9-r1
From: libxml2/libxml2@2.9.9-r3
From: libxslt/libxslt@1.1.33-r3 > libxml2/libxml2@2.9.9-r3
From: nginx-module-xslt/nginx-module-xslt@1.17.9-r1 > libxml2/libxml2@2.9.9-r3
Fixed in: 2.9.9-r4
```
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/).
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/)
to scan all newly pushed images automatically, and you can then see the results in both Docker Hub and Docker Desktop.
![Hub vulnerability scanning](hvs.png){: style=width:75% }
{: .text-center }
## Image Layering ## Image Layering
@@ -265,6 +222,6 @@ into an nginx container. Cool, huh?
## Recap ## Recap
By understanding a little bit about how images are structured, we can build images faster and ship fewer changes. By understanding a little bit about how images are structured, we can build images faster and ship fewer changes.
Scanning images gives us confidence that the containers we are running and distributing are secure.
Multi-stage builds also help us reduce overall image size and increase final container security by separating Multi-stage builds also help us reduce overall image size and increase final container security by separating
build-time dependencies from runtime dependencies. build-time dependencies from runtime dependencies.

View File

@@ -25,19 +25,19 @@ You'll notice a few flags being used. Here's some more info on them:
docker run -dp 80:80 docker/getting-started docker run -dp 80:80 docker/getting-started
``` ```
## The Docker Dashboard ## The VSCode Extension
Before going too far, we want to highlight the Docker Dashboard, which gives Before going too far, we want to highlight the Docker VSCode Extension, which gives
you a quick view of the containers running on your machine. It gives you quick 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 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 in the To access the extension, follow the instructions
[Docker Desktop manual](https://docs.docker.com/desktop/). If you open the dashboard [here](https://code.visualstudio.com/docs/containers/overview). If you open the extension
now, you will see this tutorial running! The container name (`jolly_bouman` below) is a now, you will see this tutorial running! The container name (`angry_taussig` below) is a
randomly created name. So, you'll most likely have a different name. randomly created name. So, you'll most likely have a different name.
![Tutorial container running in Docker Dashboard](tutorial-in-dashboard.png) ![Tutorial container running in Docker Extension](vs-tutorial-in-extension.png)
## What is a container? ## What is a container?

View File

@@ -4,12 +4,12 @@ application stack. The following question often arises - "Where will MySQL run?
container or run it separately?" In general, **each container should do one thing and do it well.** A few container or run it separately?" In general, **each container should do one thing and do it well.** A few
reasons: reasons:
- There's a good chance you'd have to scale APIs and front-ends differently than databases. - There's a good chance you'd have to scale APIs and front-ends differently than databases
- Separate containers let you version and update versions in isolation. - Separate containers let you version and update versions in isolation
- While you may use a container for the database locally, you may want to use a managed service - While you may use a container for the database locally, you may want to use a managed service
for the database in production. You don't want to ship your database engine with your app then. for the database in production. You don't want to ship your database engine with your app then.
- Running multiple processes will require a process manager (the container only starts one process), - Running multiple processes will require a process manager (the container only starts one process),
which adds complexity to container startup/shutdown. which adds complexity to container startup/shutdown
And there are more reasons. So, we will update our application to work like this: And there are more reasons. So, we will update our application to work like this:
@@ -37,8 +37,8 @@ For now, we will create the network first and attach the MySQL container at star
docker network create todo-app 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 1. Start a MySQL container and attach it 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/)). database will use to initialize the database (see the "Environment Variables" section in the [MySQL Docker Hub listing](https://hub.docker.com/_/mysql/)) (replace the ` \ ` characters with `` ` `` in Windows PowerShell).
```bash ```bash
docker run -d \ docker run -d \
@@ -49,17 +49,6 @@ For now, we will create the network first and attach the MySQL container at star
mysql:5.7 mysql:5.7
``` ```
If you are using PowerShell then use this command.
```powershell
docker run -d `
--network todo-app --network-alias mysql `
-v todo-mysql-data:/var/lib/mysql `
-e MYSQL_ROOT_PASSWORD=secret `
-e MYSQL_DATABASE=todos `
mysql:5.7
```
You'll also see we specified the `--network-alias` flag. We'll come back to that in just a moment. You'll also see we specified the `--network-alias` flag. We'll come back to that in just a moment.
!!! info "Pro-tip" !!! info "Pro-tip"
@@ -67,20 +56,6 @@ For now, we will create the network first and attach the MySQL container at star
where MySQL stores its data. However, we never ran a `docker volume create` command. Docker recognizes we want 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. to use a named volume and creates one automatically for us.
!!! info "Troubleshooting"
If you see a `docker: no matching manifest` error, it's because you're trying to run the container in a different
architecture than amd64, which is the only supported architecture for the mysql image at the moment. To solve this
add the flag `--platform linux/amd64` in the previous command. So your new command should look like this:
```bash
docker run -d \
--network todo-app --network-alias mysql --platform linux/amd64 \
-v todo-mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=todos \
mysql:5.7
```
1. To confirm we have the database up and running, connect to the database and verify it connects. 1. To confirm we have the database up and running, connect to the database and verify it connects.
```bash ```bash
@@ -111,8 +86,6 @@ 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! Hooray! We have our `todos` database and it's ready for us to use!
To exit the sql terminal type `exit` in the terminal.
## Connecting to MySQL ## Connecting to MySQL
@@ -183,7 +156,7 @@ The todo app supports the setting of a few environment variables to specify MySQ
A more secure mechanism is to use the secret support provided by your container orchestration framework. In most cases, 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) 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. also support env vars with a `_FILE` suffix to point to a file containing the file.
As an example, setting the `MYSQL_PASSWORD_FILE` var will cause the app to use the contents of the referenced file 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 as the connection password. Docker doesn't do anything to support these env vars. Your app will need to know to look for
@@ -192,11 +165,11 @@ The todo app supports the setting of a few environment variables to specify MySQ
With all of that explained, let's start our dev-ready container! With all of that explained, let's start our dev-ready container!
1. We'll specify each of the environment variables above, as well as connect the container to our app network. 1. We'll specify each of the environment variables above, as well as connect the container to our app network (replace the ` \ ` characters with `` ` `` in Windows PowerShell).
```bash hl_lines="3 4 5 6 7" ```bash hl_lines="3 4 5 6 7"
docker run -dp 3000:3000 \ docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \ -w /app -v ${PWD}:/app \
--network todo-app \ --network todo-app \
-e MYSQL_HOST=mysql \ -e MYSQL_HOST=mysql \
-e MYSQL_USER=root \ -e MYSQL_USER=root \
@@ -206,34 +179,6 @@ With all of that explained, let's start our dev-ready container!
sh -c "yarn install && yarn run dev" sh -c "yarn install && yarn run dev"
``` ```
If you updated your docker file in the Bind Mount section of the tutorial use the updated command:
```bash hl_lines="3 4 5 6 7"
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
--network todo-app \
-e MYSQL_HOST=mysql \
-e MYSQL_USER=root \
-e MYSQL_PASSWORD=secret \
-e MYSQL_DB=todos \
node:12-alpine \
sh -c "apk --no-cache --virtual build-dependencies add python2 make g++ && yarn install && yarn run dev"
```
If you are using PowerShell then use this command.
```powershell hl_lines="3 4 5 6 7"
docker run -dp 3000:3000 `
-w /app -v "$(pwd):/app" `
--network todo-app `
-e MYSQL_HOST=mysql `
-e MYSQL_USER=root `
-e MYSQL_PASSWORD=secret `
-e MYSQL_DB=todos `
node:12-alpine `
sh -c "yarn install && yarn run dev"
```
1. If we look at the logs for the container (`docker logs <container-id>`), we should see a message indicating it's 1. If we look at the logs for the container (`docker logs <container-id>`), we should see a message indicating it's
using the mysql database. using the mysql database.
@@ -254,7 +199,7 @@ With all of that explained, let's start our dev-ready container!
is **secret**. is **secret**.
```bash ```bash
docker exec -it <mysql-container-id> mysql -p todos docker exec -ti <mysql-container-id> mysql -p todos
``` ```
And in the mysql shell, run the following: And in the mysql shell, run the following:
@@ -271,10 +216,10 @@ With all of that explained, let's start our dev-ready container!
Obviously, your table will look different because it has your items. But, you should see them stored there! Obviously, your table will look different because it has your items. But, you should see them stored there!
If you take a quick look at the Docker Dashboard, you'll see that we have two app containers running. But, there's If you take a quick look at the Docker extension, you'll see that we have two app containers running. But, there's
no real indication that they are grouped together in a single app. We'll see how to make that better shortly! no real indication that they are grouped together in a single app. We'll see how to make that better shortly!
![Docker Dashboard showing two ungrouped app containers](dashboard-multi-container-app.png) ![Docker Dashboard showing two ungrouped app containers](vs-multi-container-app.png)
## Recap ## Recap

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@@ -38,8 +38,6 @@ see a few flaws in the Dockerfile below. But, don't worry! We'll go over them.
```dockerfile ```dockerfile
FROM node:12-alpine FROM node:12-alpine
# Adding build tools to make yarn install work on Apple silicon / arm64 machines
RUN apk add --no-cache python2 g++ make
WORKDIR /app WORKDIR /app
COPY . . COPY . .
RUN yarn install --production RUN yarn install --production
@@ -99,10 +97,10 @@ command (remember that from earlier?).
At this point, you should have a running todo list manager with a few items, all built by you! At this point, you should have a running todo list manager with a few items, all built by you!
Now, let's make a few changes and learn about managing our containers. Now, let's make a few changes and learn about managing our containers.
If you take a quick look at the Docker Dashboard, you should see your two containers running now If you take a quick look at the VSCode extension, you should see your two containers running now
(this tutorial and your freshly launched app container)! (this tutorial and your freshly launched app container)!
![Docker Dashboard with tutorial and app containers running](dashboard-two-containers.png) ![Docker Dashboard with tutorial and app containers running](vs-two-containers.png)
## Recap ## Recap

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@@ -54,10 +54,7 @@ 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 And look! There's no `data.txt` file there! That's because it was written to the scratch space for
only the first container. only the first container.
1. Go ahead and remove the first container using the `docker rm -f <container-id>` command. 1. Go ahead and remove the first container using the `docker rm -f` command.
```bash
docker rm -f <container-id>
```
## Container Volumes ## Container Volumes
@@ -94,7 +91,7 @@ Every time you use the volume, Docker will make sure the correct data is provide
docker volume create todo-db docker volume create todo-db
``` ```
1. Stop the todo app container once again in the Dashboard (or with `docker rm -f <container-id>`), as it is still running without using the persistent volume. 1. Stop the todo app container once again in the Dashboard (or with `docker rm -f <id>`), 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 1. 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. it to `/etc/todos`, which will capture all files created at the path.
@@ -108,7 +105,7 @@ Every time you use the volume, Docker will make sure the correct data is provide
![Items added to todo list](items-added.png){: style="width: 55%; " } ![Items added to todo list](items-added.png){: style="width: 55%; " }
{: .text-center } {: .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 <container-id>` to remove it. 1. Remove the container for the todo app. Use the Dashboard or `docker ps` to get the ID and then `docker rm -f <id>` to remove it.
1. Start a new container using the same command from above. 1. Start a new container using the same command from above.

View File

@@ -58,7 +58,7 @@ an example command that you will need to run to push to this repo.
Now that our image has been built and pushed into a registry, let's try running our app on a brand 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. 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](https://labs.play-with-docker.com/). 1. Open your browser to [Play with Docker](http://play-with-docker.com).
1. Log in with your Docker Hub account. 1. Log in with your Docker Hub account.

View File

@@ -74,17 +74,16 @@ ways that we can remove the old container. Feel free to choose the path that you
### Removing a container using the Docker Dashboard ### Removing a container using the Docker Dashboard
If you open the Docker dashboard, you can remove a container with two clicks! It's certainly If you open the VSCode Extension, you can remove a container with two clicks! It's certainly
much easier than having to look up the container ID and remove it. 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 1. With the extension opened, navigate to the container and right click.
buttons appear on the right.
1. Click on the trash can icon to delete the container. 1. Click on the remove container option
1. Confirm the removal and you're done! 1. Confirm the removal and you're done!
![Docker Dashboard - removing a container](dashboard-removing-container.png) ![Docker Dashboard - removing a container](vs-removing-container.png)
### Starting our updated app container ### Starting our updated app container

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

View File

@@ -14,7 +14,7 @@ changes and then restart the application. There are equivalent tools in most oth
## 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 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 use 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), [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).
| | Named Volumes | Bind Mounts | | | Named Volumes | Bind Mounts |
| - | ------------- | ----------- | | - | ------------- | ----------- |
@@ -36,42 +36,18 @@ So, let's do it!
1. Make sure you don't have any previous `getting-started` containers running. 1. Make sure you don't have any previous `getting-started` containers running.
1. Also make sure you are in app source code directory, i.e. `/path/to/getting-started/app`. If you aren't, you can `cd` into it, .e.g: 1. Run the following command (replace the ` \ ` characters with `` ` `` in Windows PowerShell). We'll explain what's going on afterwards:
```bash
cd /path/to/getting-started/app
```
1. Now that you are in the `getting-started/app` directory, run the following command. We'll explain what's going on afterwards:
```bash ```bash
docker run -dp 3000:3000 \ docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \ -w /app -v ${PWD}:/app \
node:12-alpine \ node:12-alpine \
sh -c "yarn install && yarn run dev" sh -c "yarn install && yarn run dev"
``` ```
If you are using PowerShell then use this command.
```powershell
docker run -dp 3000:3000 `
-w /app -v "$(pwd):/app" `
node:12-alpine `
sh -c "yarn install && yarn run dev"
```
If you are using an Apple Silicon Mac or another ARM64 device then use this command.
```bash
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
node:12-alpine \
sh -c "apk add --no-cache python2 g++ make && yarn install && yarn run dev"
```
- `-dp 3000:3000` - same as before. Run in detached (background) mode and create a port mapping - `-dp 3000:3000` - same as before. Run in detached (background) mode and create a port mapping
- `-w /app` - sets the container's present working directory where the command will run from - `-w /app` - sets the "working directory" or the current directory that the command will run from
- `-v "$(pwd):/app"` - bind mount (link) the host's present `getting-started/app` directory to the container's `/app` directory. Note: Docker requires absolute paths for binding mounts, so in this example we use `pwd` for printing the absolute path of the working directory, i.e. the `app` directory, instead of typing it manually - `-v ${PWD}:/app` - bind mount the current directory from the host in the container into the `/app` directory
- `node:12-alpine` - the image to use. Note that this is the base image for our app from the Dockerfile - `node:12-alpine` - the image to use. Note that this is the base image for our app from the Dockerfile
- `sh -c "yarn install && yarn run dev"` - the command. We're starting a shell using `sh` (alpine doesn't have `bash`) and - `sh -c "yarn install && yarn run dev"` - the command. We're starting a shell using `sh` (alpine doesn't have `bash`) and
running `yarn install` to install _all_ dependencies and then running `yarn run dev`. If we look in the `package.json`, running `yarn install` to install _all_ dependencies and then running `yarn run dev`. If we look in the `package.json`,
@@ -93,7 +69,7 @@ So, let's do it!
When you're done watching the logs, exit out by hitting `Ctrl`+`C`. 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 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
"Add". This change will be on line 109 - remember to save the file. "Add". This change will be on line 109.
```diff ```diff
- {submitting ? 'Adding...' : 'Add Item'} - {submitting ? 'Adding...' : 'Add Item'}

View File

@@ -33,13 +33,13 @@ docker-compose version
for the current schema versions and the compatibility matrix. for the current schema versions and the compatibility matrix.
```yaml ```yaml
version: "3.8" version: "3.7"
``` ```
1. Next, we'll define the list of services (or containers) we want to run as part of our application. 1. Next, we'll define the list of services (or containers) we want to run as part of our application.
```yaml hl_lines="3" ```yaml hl_lines="3"
version: "3.8" version: "3.7"
services: services:
``` ```
@@ -49,11 +49,11 @@ And now, we'll start migrating a service at a time into the compose file.
## Defining the App Service ## Defining the App Service
To remember, this was the command we were using to define our app container. To remember, this was the command we were using to define our app container (replace the ` \ ` characters with `` ` `` in Windows PowerShell).
```bash ```bash
docker run -dp 3000:3000 \ docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \ -w /app -v ${PWD}:/app \
--network todo-app \ --network todo-app \
-e MYSQL_HOST=mysql \ -e MYSQL_HOST=mysql \
-e MYSQL_USER=root \ -e MYSQL_USER=root \
@@ -63,25 +63,11 @@ docker run -dp 3000:3000 \
sh -c "yarn install && yarn run dev" sh -c "yarn install && yarn run dev"
``` ```
If you are using PowerShell then use this command.
```powershell
docker run -dp 3000:3000 `
-w /app -v "$(pwd):/app" `
--network todo-app `
-e MYSQL_HOST=mysql `
-e MYSQL_USER=root `
-e MYSQL_PASSWORD=secret `
-e MYSQL_DB=todos `
node:12-alpine `
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. 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. The name will automatically become a network alias, which will be useful when defining our MySQL service.
```yaml hl_lines="4 5" ```yaml hl_lines="4 5"
version: "3.8" version: "3.7"
services: services:
app: app:
@@ -92,7 +78,7 @@ docker run -dp 3000:3000 `
So, let's go ahead and move that into our file. So, let's go ahead and move that into our file.
```yaml hl_lines="6" ```yaml hl_lines="6"
version: "3.8" version: "3.7"
services: services:
app: app:
@@ -102,11 +88,11 @@ 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 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/compose-file-v3/#short-syntax-1) here, but there is also a more verbose [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/compose-file-v3/#long-syntax-1) available as well. [long syntax](https://docs.docker.com/compose/compose-file/#long-syntax-1) available as well.
```yaml hl_lines="7 8" ```yaml hl_lines="7 8"
version: "3.8" version: "3.7"
services: services:
app: app:
@@ -116,13 +102,13 @@ docker run -dp 3000:3000 `
- 3000:3000 - 3000:3000
``` ```
1. Next, we'll migrate both the working directory (`-w /app`) and the volume mapping (`-v "$(pwd):/app"`) by using 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/compose-file-v3/#short-syntax-3) and [long](https://docs.docker.com/compose/compose-file/compose-file-v3/#long-syntax-3) syntax. 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.
One advantage of Docker Compose volume definitions is we can use relative paths from the current directory. One advantage of Docker Compose volume definitions is we can use relative paths from the current directory.
```yaml hl_lines="9 10 11" ```yaml hl_lines="9 10 11"
version: "3.8" version: "3.7"
services: services:
app: app:
@@ -138,7 +124,7 @@ docker run -dp 3000:3000 `
1. Finally, we need to migrate the environment variable definitions using the `environment` key. 1. Finally, we need to migrate the environment variable definitions using the `environment` key.
```yaml hl_lines="12 13 14 15 16" ```yaml hl_lines="12 13 14 15 16"
version: "3.8" version: "3.7"
services: services:
app: app:
@@ -159,7 +145,7 @@ docker run -dp 3000:3000 `
### Defining the MySQL Service ### Defining 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 we used for that container was the following (replace the ` \ ` characters with `` ` `` in Windows PowerShell):
```bash ```bash
docker run -d \ docker run -d \
@@ -170,22 +156,11 @@ docker run -d \
mysql:5.7 mysql:5.7
``` ```
If you are using PowerShell then use this command.
```powershell
docker run -d `
--network todo-app --network-alias mysql `
-v todo-mysql-data:/var/lib/mysql `
-e MYSQL_ROOT_PASSWORD=secret `
-e MYSQL_DATABASE=todos `
mysql:5.7
```
1. We will first define the new service and name it `mysql` so it automatically gets the network alias. We'll 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. go ahead and specify the image to use as well.
```yaml hl_lines="6 7" ```yaml hl_lines="6 7"
version: "3.8" version: "3.7"
services: services:
app: app:
@@ -197,10 +172,10 @@ docker run -d `
1. Next, we'll define the volume mapping. When we ran the container with `docker run`, the named volume was created 1. 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 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, `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/compose-file-v3/#volume-configuration-reference) though. the default options are used. There are [many more options available](https://docs.docker.com/compose/compose-file/#volume-configuration-reference) though.
```yaml hl_lines="8 9 10 11 12" ```yaml hl_lines="8 9 10 11 12"
version: "3.8" version: "3.7"
services: services:
app: app:
@@ -217,7 +192,7 @@ docker run -d `
1. Finally, we only need to specify the environment variables. 1. Finally, we only need to specify the environment variables.
```yaml hl_lines="10 11 12" ```yaml hl_lines="10 11 12"
version: "3.8" version: "3.7"
services: services:
app: app:
@@ -238,7 +213,7 @@ At this point, our complete `docker-compose.yml` should look like this:
```yaml ```yaml
version: "3.8" version: "3.7"
services: services:
app: app:
@@ -318,19 +293,15 @@ Now that we have our `docker-compose.yml` file, we can start it up!
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! 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!
## Seeing our App Stack in Docker Dashboard ## Seeing our App Stack in the Docker Extension
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 we look at the Docker Extension, we can changing our grouping options using the 'cog' and 'group by'. In this instance we want to see containers sharing a network.
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.
![Docker Dashboard with app project](dashboard-app-project-collapsed.png) ![VS Extension with network](vs-app-project-collapsed.png)
If you twirl down the app, you will see the two containers we defined in the compose file. The names are also a little If you twirl down the network, you will see the two containers we defined in the compose file.
more descriptive, as they follow the pattern of `<project-name>_<service-name>_<replica-number>`. So, it's very easy to
quickly see what container is our app and which container is the mysql database.
![Docker Dashboard with app project expanded](dashboard-app-project-expanded.png) ![VS Extension with app network expanded](vs-app-project-expanded.png)
## Tearing it All Down ## Tearing it All Down

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

View File

@@ -1,5 +1,5 @@
mkdocs==1.3.0 mkdocs==1.0.4
mkdocs-material==4.6.3 mkdocs-material==4.6.3
mkdocs-minify-plugin==0.2.3 mkdocs-minify-plugin==0.2.3
pygments==2.7.4 pygments==2.6.1
pymdown-extensions==7.0 pymdown-extensions==7.0