Compare commits
103 Commits
vscode
...
atomist/pi
Author | SHA1 | Date | |
---|---|---|---|
|
37e489af74 | ||
|
9d378893cb | ||
|
113eea7de5 | ||
|
6f818a549f | ||
|
cb16e5d1f3 | ||
|
7d6a447fca | ||
|
0fdedec7a2 | ||
|
9a4c1b53dd | ||
|
1fd29da9be | ||
|
2dac6361da | ||
|
858d6c7607 | ||
|
16d65a70fe | ||
|
664ad9edab | ||
|
95a8d8a72b | ||
|
d5044a9db7 | ||
|
96670a1d03 | ||
|
5abe931855 | ||
|
8801e0e0ca | ||
|
9b5581d3bd | ||
|
798c396e89 | ||
|
9eab81d81e | ||
|
720eadbeae | ||
|
1bec479199 | ||
|
2be5c745e8 | ||
|
8725352c3f | ||
|
f1f2012af5 | ||
|
9ddebfdd36 | ||
|
9bf480301d | ||
|
d35fc60923 | ||
|
6ab1ec709f | ||
|
56890c941a | ||
|
e96065a503 | ||
|
5c1574e643 | ||
|
b37be73687 | ||
|
42f8dbe70c | ||
|
a1b127be03 | ||
|
9bccc3cf99 | ||
|
5ded522cbf | ||
|
ace32adb9d | ||
|
5572d7a5b3 | ||
|
572dc47f99 | ||
|
5c65399cec | ||
|
6086449d15 | ||
|
5c00304375 | ||
|
0efc3a5c19 | ||
|
782d9421ae | ||
|
d002206c3e | ||
|
e04817f421 | ||
|
0f44699cfa | ||
|
966b2e2857 | ||
|
de74d48616 | ||
|
14c67643bb | ||
|
acdcd83ced | ||
|
8511b9af07 | ||
|
f2af4b0ae4 | ||
|
7ceaaee2a7 | ||
|
25f25d8126 | ||
|
8a8994297d | ||
|
4e7c2668fc | ||
|
7bb2ef8c6d | ||
|
433353af1c | ||
|
ac4adc8665 | ||
|
67e75bb1cb | ||
|
06d835a3cd | ||
|
9950c06246 | ||
|
8dd3914433 | ||
|
958126d5a7 | ||
|
f390971d25 | ||
|
64a1666f12 | ||
|
5d5e551104 | ||
|
13386236e4 | ||
|
2376af82e7 | ||
|
0edef34461 | ||
|
e991a5ab73 | ||
|
62e2117581 | ||
|
4b6b5476c5 | ||
|
e43a605d37 | ||
|
eccb882c59 | ||
|
dbae842f9c | ||
|
dcfbefe0af | ||
|
e9f8d4443a | ||
|
3de6451f5c | ||
|
b66f1c3224 | ||
|
23e02b9a44 | ||
|
5cccd65849 | ||
|
9646231353 | ||
|
3cbe2e686e | ||
|
172c616131 | ||
|
a2932698bd | ||
|
6190776cb6 | ||
|
3323acf03e | ||
|
559d5f335e | ||
|
6916e6a595 | ||
|
bb961ef28d | ||
|
0b402b3ebf | ||
|
4ed7232ea2 | ||
|
9f31a47053 | ||
|
b1d106ea7c | ||
|
288a57ea63 | ||
|
f232e36815 | ||
|
fe2686fe00 | ||
|
a33ed89ab3 | ||
|
f77065be98 |
12
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
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
|
19
Dockerfile
@@ -1,23 +1,28 @@
|
||||
# Install the base requirements for the app.
|
||||
# This stage is to support development.
|
||||
FROM python:alpine AS base
|
||||
FROM python:alpine@sha256:c9d3c11e89887c82efeb4f4fee8771a406cf42f41aebbd23148906d5fe3c1426 AS base
|
||||
WORKDIR /app
|
||||
COPY requirements.txt .
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
# Run tests to validate app
|
||||
FROM node:12-alpine AS app-base
|
||||
FROM node:12-alpine@sha256:d4b15b3d48f42059a15bd659be60afe21762aae9d6cbea6f124440895c27db68 AS app-base
|
||||
WORKDIR /app
|
||||
COPY app/package.json app/yarn.lock ./
|
||||
RUN yarn install
|
||||
COPY app/spec ./spec
|
||||
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
|
||||
|
||||
# Clear out the node_modules and create the zip
|
||||
FROM app-base AS app-zip-creator
|
||||
RUN rm -rf node_modules && \
|
||||
apk add zip && \
|
||||
COPY app/package.json app/yarn.lock ./
|
||||
COPY app/spec ./spec
|
||||
COPY app/src ./src
|
||||
RUN apk add zip && \
|
||||
zip -r /app.zip /app
|
||||
|
||||
# Dev-ready container - actual files will be mounted in
|
||||
@@ -31,6 +36,6 @@ RUN mkdocs build
|
||||
|
||||
# Extract the static content from the build
|
||||
# and use a nginx image to serve the content
|
||||
FROM nginx:alpine
|
||||
FROM nginx:alpine@sha256:082f8c10bd47b6acc8ef15ae61ae45dd8fde0e9f389a8b5cb23c37408642bf5d
|
||||
COPY --from=app-zip-creator /app.zip /usr/share/nginx/html/assets/app.zip
|
||||
COPY --from=build /app/site /usr/share/nginx/html
|
||||
|
4
Jenkinsfile
vendored
@@ -10,7 +10,7 @@ pipeline {
|
||||
when {
|
||||
branch 'master'
|
||||
}
|
||||
sh "docker build docker/getting-started ."
|
||||
sh "docker build -t docker/getting-started ."
|
||||
|
||||
steps {
|
||||
withDockerRegistry([url: "", credentialsId: "dockerbuildbot-index.docker.io"]) {
|
||||
@@ -19,4 +19,4 @@ pipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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 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.
|
||||
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.
|
||||
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!
|
||||
|
@@ -9,13 +9,15 @@
|
||||
"dev": "nodemon src/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"body-parser": "^1.19.0",
|
||||
"express": "^4.17.1",
|
||||
"mysql": "^2.17.1",
|
||||
"sqlite3": "^4.1.0",
|
||||
"sqlite3": "^5.0.0",
|
||||
"uuid": "^3.3.3",
|
||||
"wait-port": "^0.2.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"ansi-regex": "5.0.1"
|
||||
},
|
||||
"prettier": {
|
||||
"trailingComma": "all",
|
||||
"tabWidth": 4,
|
||||
@@ -24,8 +26,8 @@
|
||||
"singleQuote": true
|
||||
},
|
||||
"devDependencies": {
|
||||
"jest": "^24.9.0",
|
||||
"nodemon": "^1.19.2",
|
||||
"jest": "^27.2.5",
|
||||
"nodemon": "^2.0.13",
|
||||
"prettier": "^1.18.2"
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
const db = require('../../src/persistence/sqlite');
|
||||
const fs = require('fs');
|
||||
const location = process.env.SQLITE_DB_LOCATION || '/etc/todos/todo.db';
|
||||
|
||||
const ITEM = {
|
||||
id: '7aef3d7c-d301-4846-8358-2a91ec9d6be3',
|
||||
@@ -8,8 +9,8 @@ const ITEM = {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
if (fs.existsSync('/etc/todos/todo.db')) {
|
||||
fs.unlinkSync('/etc/todos/todo.db');
|
||||
if (fs.existsSync(location)) {
|
||||
fs.unlinkSync(location);
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -6,7 +6,7 @@ const addItem = require('./routes/addItem');
|
||||
const updateItem = require('./routes/updateItem');
|
||||
const deleteItem = require('./routes/deleteItem');
|
||||
|
||||
app.use(require('body-parser').json());
|
||||
app.use(express.json());
|
||||
app.use(express.static(__dirname + '/static'));
|
||||
|
||||
app.get('/items', getItems);
|
||||
|
@@ -29,11 +29,12 @@ async function init() {
|
||||
user,
|
||||
password,
|
||||
database,
|
||||
charset: 'utf8mb4',
|
||||
});
|
||||
|
||||
return new Promise((acc, rej) => {
|
||||
pool.query(
|
||||
'CREATE TABLE IF NOT EXISTS todo_items (id varchar(36), name varchar(255), completed boolean)',
|
||||
'CREATE TABLE IF NOT EXISTS todo_items (id varchar(36), name varchar(255), completed boolean) DEFAULT CHARSET utf8mb4',
|
||||
err => {
|
||||
if (err) return rej(err);
|
||||
|
||||
|
5036
app/yarn.lock
2
build.sh
@@ -9,6 +9,6 @@ else
|
||||
fi
|
||||
|
||||
docker buildx build \
|
||||
--platform linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6 \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
-t docker/getting-started:latest \
|
||||
$( (( $WILL_PUSH == 1 )) && printf %s '--push' ) .
|
||||
|
BIN
docs/tutorial/image-building-best-practices/hvs.png
Normal file
After Width: | Height: | Size: 125 KiB |
@@ -1,3 +1,46 @@
|
||||
## 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.
|
||||
|
||||
{: style=width:75% }
|
||||
{: .text-center }
|
||||
|
||||
## Image Layering
|
||||
|
||||
@@ -222,6 +265,6 @@ into an nginx container. Cool, huh?
|
||||
## Recap
|
||||
|
||||
By understanding a little bit about how images are structured, we can build images faster and ship fewer changes.
|
||||
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
|
||||
build-time dependencies from runtime dependencies.
|
||||
|
||||
|
@@ -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
|
||||
```
|
||||
|
||||
## The VSCode Extension
|
||||
## The Docker Dashboard
|
||||
|
||||
Before going too far, we want to highlight the Docker VSCode Extension, which gives
|
||||
Before going too far, we want to highlight the Docker Dashboard, which gives
|
||||
you a quick view of the containers running on your machine. It gives you quick
|
||||
access to container logs, lets you get a shell inside the container, and lets you
|
||||
easily manage container lifecycle (stop, remove, etc.).
|
||||
|
||||
To access the extension, follow the instructions
|
||||
[here](https://code.visualstudio.com/docs/containers/overview). If you open the extension
|
||||
now, you will see this tutorial running! The container name (`angry_taussig` below) is a
|
||||
To access the dashboard, follow the instructions in the
|
||||
[Docker Desktop manual](https://docs.docker.com/desktop/). If you open the dashboard
|
||||
now, you will see this tutorial running! The container name (`jolly_bouman` below) is a
|
||||
randomly created name. So, you'll most likely have a different name.
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## What is a container?
|
||||
|
@@ -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
|
||||
reasons:
|
||||
|
||||
- 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
|
||||
- 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.
|
||||
- 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.
|
||||
- Running multiple processes will require a process manager (the container only starts one process),
|
||||
which adds complexity to container startup/shutdown
|
||||
- Running multiple processes will require a process manager (the container only starts one process),
|
||||
which adds complexity to container startup/shutdown.
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
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/)) (replace the ` \ ` characters with `` ` `` in Windows PowerShell).
|
||||
1. Start a MySQL container and attach it to the network. We're also going to define a few environment variables that the
|
||||
database will use to initialize the database (see the "Environment Variables" section in the [MySQL Docker Hub listing](https://hub.docker.com/_/mysql/)).
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
@@ -49,6 +49,17 @@ For now, we will create the network first and attach the MySQL container at star
|
||||
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.
|
||||
|
||||
!!! info "Pro-tip"
|
||||
@@ -56,6 +67,20 @@ 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
|
||||
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.
|
||||
|
||||
```bash
|
||||
@@ -86,6 +111,8 @@ 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!
|
||||
|
||||
To exit the sql terminal type `exit` in the terminal.
|
||||
|
||||
|
||||
## Connecting to MySQL
|
||||
|
||||
@@ -150,26 +177,26 @@ The todo app supports the setting of a few environment variables to specify MySQ
|
||||
|
||||
!!! warning Setting Connection Settings via Env Vars
|
||||
While using env vars to set connection settings is generally ok for development, it is **HIGHLY DISCOURAGED**
|
||||
when running applications in production. Diogo Monica, the former lead of security at Docker,
|
||||
when running applications in production. Diogo Monica, the former lead of security at Docker,
|
||||
[wrote a fantastic blog post](https://diogomonica.com/2017/03/27/why-you-shouldnt-use-env-variables-for-secret-data/)
|
||||
explaining why.
|
||||
|
||||
explaining why.
|
||||
|
||||
A more secure mechanism is to use the secret support provided by your container orchestration framework. In most cases,
|
||||
these secrets are mounted as files in the running container. You'll see many apps (including the MySQL image and the todo app)
|
||||
also support env vars with a `_FILE` suffix to point to a file containing the file.
|
||||
|
||||
As an example, setting the `MYSQL_PASSWORD_FILE` var will cause the app to use the contents of the referenced file
|
||||
also support env vars with a `_FILE` suffix to point to a file containing the variable.
|
||||
|
||||
As an example, setting the `MYSQL_PASSWORD_FILE` var will cause the app to use the contents of the referenced file
|
||||
as the connection password. Docker doesn't do anything to support these env vars. Your app will need to know to look for
|
||||
the variable and get the file contents.
|
||||
|
||||
|
||||
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 (replace the ` \ ` characters with `` ` `` in Windows PowerShell).
|
||||
1. We'll specify each of the environment variables above, as well as connect the container to our app network.
|
||||
|
||||
```bash hl_lines="3 4 5 6 7"
|
||||
docker run -dp 3000:3000 \
|
||||
-w /app -v ${PWD}:/app \
|
||||
-w /app -v "$(pwd):/app" \
|
||||
--network todo-app \
|
||||
-e MYSQL_HOST=mysql \
|
||||
-e MYSQL_USER=root \
|
||||
@@ -179,6 +206,34 @@ With all of that explained, let's start our dev-ready container!
|
||||
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
|
||||
using the mysql database.
|
||||
|
||||
@@ -199,7 +254,7 @@ With all of that explained, let's start our dev-ready container!
|
||||
is **secret**.
|
||||
|
||||
```bash
|
||||
docker exec -ti <mysql-container-id> mysql -p todos
|
||||
docker exec -it <mysql-container-id> mysql -p todos
|
||||
```
|
||||
|
||||
And in the mysql shell, run the following:
|
||||
@@ -216,10 +271,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!
|
||||
|
||||
If you take a quick look at the Docker extension, you'll see that we have two app containers running. But, there's
|
||||
If you take a quick look at the Docker Dashboard, 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!
|
||||
|
||||

|
||||

|
||||
|
||||
## Recap
|
||||
|
||||
|
Before Width: | Height: | Size: 46 KiB |
@@ -38,6 +38,8 @@ see a few flaws in the Dockerfile below. But, don't worry! We'll go over them.
|
||||
|
||||
```dockerfile
|
||||
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
|
||||
COPY . .
|
||||
RUN yarn install --production
|
||||
@@ -97,10 +99,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!
|
||||
Now, let's make a few changes and learn about managing our containers.
|
||||
|
||||
If you take a quick look at the VSCode extension, you should see your two containers running now
|
||||
If you take a quick look at the Docker Dashboard, you should see your two containers running now
|
||||
(this tutorial and your freshly launched app container)!
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## Recap
|
||||
|
Before Width: | Height: | Size: 68 KiB |
@@ -54,7 +54,10 @@ What you'll see is that the files created in one container aren't available in a
|
||||
And look! There's no `data.txt` file there! That's because it was written to the scratch space for
|
||||
only the first container.
|
||||
|
||||
1. Go ahead and remove the first container using the `docker rm -f` command.
|
||||
1. Go ahead and remove the first container using the `docker rm -f <container-id>` command.
|
||||
```bash
|
||||
docker rm -f <container-id>
|
||||
```
|
||||
|
||||
## Container Volumes
|
||||
|
||||
@@ -91,7 +94,7 @@ Every time you use the volume, Docker will make sure the correct data is provide
|
||||
docker volume create todo-db
|
||||
```
|
||||
|
||||
1. Stop the todo app container once again in the Dashboard (or with `docker rm -f <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 <container-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
|
||||
it to `/etc/todos`, which will capture all files created at the path.
|
||||
@@ -105,7 +108,7 @@ Every time you use the volume, Docker will make sure the correct data is provide
|
||||
{: style="width: 55%; " }
|
||||
{: .text-center }
|
||||
|
||||
1. Remove the container for the todo app. Use the Dashboard or `docker ps` to get the ID and then `docker rm -f <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 <container-id>` to remove it.
|
||||
|
||||
1. Start a new container using the same command from above.
|
||||
|
||||
|
@@ -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
|
||||
new instance that has never seen this container image! To do this, we will use Play with Docker.
|
||||
|
||||
1. Open your browser to [Play with Docker](http://play-with-docker.com).
|
||||
1. Open your browser to [Play with Docker](https://labs.play-with-docker.com/).
|
||||
|
||||
1. Log in with your Docker Hub account.
|
||||
|
||||
@@ -89,4 +89,4 @@ can use the latest version of the image.
|
||||
Now that we have that figured out, let's circle back around to what we noticed at the end of the last
|
||||
section. As a reminder, we noticed that when we restarted the app, we lost all of our todo list items.
|
||||
That's obviously not a great user experience, so let's learn how we can persist the data across
|
||||
restarts!
|
||||
restarts!
|
||||
|
@@ -74,16 +74,17 @@ ways that we can remove the old container. Feel free to choose the path that you
|
||||
|
||||
### Removing a container using the Docker Dashboard
|
||||
|
||||
If you open the VSCode Extension, you can remove a container with two clicks! It's certainly
|
||||
If you open the Docker dashboard, you can remove a container with two clicks! It's certainly
|
||||
much easier than having to look up the container ID and remove it.
|
||||
|
||||
1. With the extension opened, navigate to the container and right click.
|
||||
1. With the dashboard opened, hover over the app container and you'll see a collection of action
|
||||
buttons appear on the right.
|
||||
|
||||
1. Click on the remove container option
|
||||
1. Click on the trash can icon to delete the container.
|
||||
|
||||
1. Confirm the removal and you're done!
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
### Starting our updated app container
|
||||
|
Before Width: | Height: | Size: 153 KiB |
@@ -14,7 +14,7 @@ changes and then restart the application. There are equivalent tools in most oth
|
||||
## Quick Volume Type Comparisons
|
||||
|
||||
Bind mounts and named volumes are the two main types of volumes that come with the Docker engine. However, additional
|
||||
volume drivers are available to support other uses cases ([SFTP](https://github.com/vieux/docker-volume-sshfs), [Ceph](https://ceph.com/geen-categorie/getting-started-with-the-docker-rbd-volume-plugin/), [NetApp](https://netappdvp.readthedocs.io/en/stable/), [S3](https://github.com/elementar/docker-s3-volume), and more).
|
||||
volume drivers are available to support other 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).
|
||||
|
||||
| | Named Volumes | Bind Mounts |
|
||||
| - | ------------- | ----------- |
|
||||
@@ -36,18 +36,42 @@ So, let's do it!
|
||||
|
||||
1. Make sure you don't have any previous `getting-started` containers running.
|
||||
|
||||
1. Run the following command (replace the ` \ ` characters with `` ` `` in Windows PowerShell). We'll explain what's going on afterwards:
|
||||
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:
|
||||
|
||||
```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
|
||||
docker run -dp 3000:3000 \
|
||||
-w /app -v ${PWD}:/app \
|
||||
-w /app -v "$(pwd):/app" \
|
||||
node:12-alpine \
|
||||
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
|
||||
- `-w /app` - sets the "working directory" or the current directory that the command will run from
|
||||
- `-v ${PWD}:/app` - bind mount the current directory from the host in the container into the `/app` directory
|
||||
- `-w /app` - sets the container's present working directory where 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
|
||||
- `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
|
||||
running `yarn install` to install _all_ dependencies and then running `yarn run dev`. If we look in the `package.json`,
|
||||
@@ -69,7 +93,7 @@ So, let's do it!
|
||||
When you're done watching the logs, exit out by hitting `Ctrl`+`C`.
|
||||
|
||||
1. Now, let's make a change to the app. In the `src/static/js/app.js` file, let's change the "Add Item" button to simply say
|
||||
"Add". This change will be on line 109.
|
||||
"Add". This change will be on line 109 - remember to save the file.
|
||||
|
||||
```diff
|
||||
- {submitting ? 'Adding...' : 'Add Item'}
|
||||
|
@@ -33,13 +33,13 @@ docker-compose version
|
||||
for the current schema versions and the compatibility matrix.
|
||||
|
||||
```yaml
|
||||
version: "3.7"
|
||||
version: "3.8"
|
||||
```
|
||||
|
||||
1. Next, we'll define the list of services (or containers) we want to run as part of our application.
|
||||
|
||||
```yaml hl_lines="3"
|
||||
version: "3.7"
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
```
|
||||
@@ -49,11 +49,11 @@ And now, we'll start migrating a service at a time into the compose file.
|
||||
|
||||
## Defining the App Service
|
||||
|
||||
To remember, this was the command we were using to define our app container (replace the ` \ ` characters with `` ` `` in Windows PowerShell).
|
||||
To remember, this was the command we were using to define our app container.
|
||||
|
||||
```bash
|
||||
docker run -dp 3000:3000 \
|
||||
-w /app -v ${PWD}:/app \
|
||||
-w /app -v "$(pwd):/app" \
|
||||
--network todo-app \
|
||||
-e MYSQL_HOST=mysql \
|
||||
-e MYSQL_USER=root \
|
||||
@@ -63,11 +63,25 @@ docker run -dp 3000:3000 \
|
||||
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.
|
||||
The name will automatically become a network alias, which will be useful when defining our MySQL service.
|
||||
|
||||
```yaml hl_lines="4 5"
|
||||
version: "3.7"
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
@@ -78,7 +92,7 @@ docker run -dp 3000:3000 \
|
||||
So, let's go ahead and move that into our file.
|
||||
|
||||
```yaml hl_lines="6"
|
||||
version: "3.7"
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
@@ -88,11 +102,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
|
||||
[short syntax](https://docs.docker.com/compose/compose-file/#short-syntax-1) here, but there is also a more verbose
|
||||
[long syntax](https://docs.docker.com/compose/compose-file/#long-syntax-1) available as well.
|
||||
[short syntax](https://docs.docker.com/compose/compose-file/compose-file-v3/#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.
|
||||
|
||||
```yaml hl_lines="7 8"
|
||||
version: "3.7"
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
@@ -102,13 +116,13 @@ docker run -dp 3000:3000 \
|
||||
- 3000:3000
|
||||
```
|
||||
|
||||
1. Next, we'll migrate both the working directory (`-w /app`) and the volume mapping (`-v ${PWD}:/app`) by using
|
||||
the `working_dir` and `volumes` definitions. Volumes also has a [short](https://docs.docker.com/compose/compose-file/#short-syntax-3) and [long](https://docs.docker.com/compose/compose-file/#long-syntax-3) syntax.
|
||||
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.
|
||||
|
||||
One advantage of Docker Compose volume definitions is we can use relative paths from the current directory.
|
||||
|
||||
```yaml hl_lines="9 10 11"
|
||||
version: "3.7"
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
@@ -124,7 +138,7 @@ docker run -dp 3000:3000 \
|
||||
1. Finally, we need to migrate the environment variable definitions using the `environment` key.
|
||||
|
||||
```yaml hl_lines="12 13 14 15 16"
|
||||
version: "3.7"
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
@@ -145,7 +159,7 @@ docker run -dp 3000:3000 \
|
||||
|
||||
### Defining the MySQL Service
|
||||
|
||||
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):
|
||||
Now, it's time to define the MySQL service. The command that we used for that container was the following:
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
@@ -156,11 +170,22 @@ docker run -d \
|
||||
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
|
||||
go ahead and specify the image to use as well.
|
||||
|
||||
```yaml hl_lines="6 7"
|
||||
version: "3.7"
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
@@ -172,10 +197,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
|
||||
automatically. However, that doesn't happen when running with Compose. We need to define the volume in the top-level
|
||||
`volumes:` section and then specify the mountpoint in the service config. By simply providing only the volume name,
|
||||
the default options are used. There are [many more options available](https://docs.docker.com/compose/compose-file/#volume-configuration-reference) though.
|
||||
the default options are used. There are [many more options available](https://docs.docker.com/compose/compose-file/compose-file-v3/#volume-configuration-reference) though.
|
||||
|
||||
```yaml hl_lines="8 9 10 11 12"
|
||||
version: "3.7"
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
@@ -192,7 +217,7 @@ docker run -d \
|
||||
1. Finally, we only need to specify the environment variables.
|
||||
|
||||
```yaml hl_lines="10 11 12"
|
||||
version: "3.7"
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
@@ -213,7 +238,7 @@ At this point, our complete `docker-compose.yml` should look like this:
|
||||
|
||||
|
||||
```yaml
|
||||
version: "3.7"
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
@@ -293,15 +318,19 @@ 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!
|
||||
|
||||
## Seeing our App Stack in the Docker Extension
|
||||
## Seeing our App Stack in Docker Dashboard
|
||||
|
||||
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.
|
||||
If we look at the Docker Dashboard, we'll see that there is a group named **app**. This is the "project name" from Docker
|
||||
Compose and used to group the containers together. By default, the project name is simply the name of the directory that the
|
||||
`docker-compose.yml` was located in.
|
||||
|
||||

|
||||

|
||||
|
||||
If you twirl down the network, you will see the two containers we defined in the compose file.
|
||||
If you twirl down the app, you will see the two containers we defined in the compose file. The names are also a little
|
||||
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.
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## Tearing it All Down
|
||||
|
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 316 KiB |
@@ -1,5 +1,5 @@
|
||||
mkdocs==1.0.4
|
||||
mkdocs==1.3.0
|
||||
mkdocs-material==4.6.3
|
||||
mkdocs-minify-plugin==0.2.3
|
||||
pygments==2.6.1
|
||||
pygments==2.7.4
|
||||
pymdown-extensions==7.0
|
||||
|