【Docker】D3.开始使用
目录1.入门1.1.命令1.2.什么是容器?1.3.什么是容器镜像?2.应用程序2.1.新建2.2.更新2.2.共享3.持久化数据库4.使用绑定挂载4.1.启动一个开发模式容器5.多容器应用5.1.容器网络5.2.启动 MySQL5.3.连接到 MySQL6.使用 Docker Compose6.1.安装 Docker Compose6.2.创建 Compose 文件6.3.定义应用服务6.4.定
目录
1.入门
1.1.命令
docker run -d -p 80:80 docker/getting-started
# 组合标志命令
docker run -dp 80:80 docker/getting-started
-d
以分离模式运行容器(在后台)-p 80:80
将主机的 80 端口映射到容器中的 80 端口docker/getting-started
要使用的镜像
1.2.什么是容器?
简而言之,容器是机器上的沙盒进程,与主机上的所有其他进程隔离。这种隔离利用了内核命名空间和 cgroups,这些特性在 Linux 中已经存在了很长时间。Docker 致力于使这些功能变得平易近人且易于使用。总而言之,一个容器:
- 是镜像的可运行实例。可以使用 DockerAPI 或 CLI 创建、启动、停止、移动或删除容器。
- 可以在本地机器、虚拟机上运行或部署到云端。
- 可移植(可以在任何操作系统上运行)
- 容器彼此隔离并运行自己的软件、二进制文件和配置。
1.3.什么是容器镜像?
运行容器时,它使用隔离的文件系统。此自定义文件系统由容器镜像提供。由于镜像包含容器的文件系统,它必须包含运行应用程序所需的一切——所有依赖项、配置、脚本、二进制文件等。镜像还包含容器的其他配置,例如环境变量、运行的默认命令、和其他元数据。
2.应用程序
2.1.新建
新建Dockerfile文件
构建容器镜像 docker build -t getting-started .
启动容器镜像 docker run -dp 3000:3000 getting-started
2.2.更新
获取容器id docker ps
停止容器 docker stop <the-container-id>
删除容器 docker rm
启动更新容器镜像 docker run -dp 3000:3000 getting-started
2.2.共享
推送到Docker Hub docker push docker/getting-started
登录Docker Hub docker login -u YOUR-USER-NAME
指定镜像一个新名称 docker tag getting-started YOUR-USER-NAME/getting-started
再次推送到Docker Hub docker push docker/getting-started
3.持久化数据库
Docker 维护磁盘上的物理位置。每次使用卷时,Docker 都会确保提供正确的数据。
# 1.创建卷
docker volume create todo-db
# 2.在仪表板(或使用 )中再次停止并删除待办事项应用程序容器 docker rm -f <id>,因为它仍在运行而不使用持久卷。
# 3.启动 todo 应用程序容器,但添加-v标志以指定卷安装。将使用命名卷并将其挂载到/etc/todos,这将捕获在该路径创建的所有文件。
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
# 4.容器启动后,打开应用程序并将一些项目添加到待办事项列表中。
# 5.停止并删除 todo 应用程序的容器。使用仪表板或docker ps获取 ID,然后docker rm -f <id>将其删除。
# 6.使用上面的相同命令启动一个新容器。
# 7.打开应用程序。应该会看到您的项目仍在列表中!
# 完成检查列表后,继续删除容器。
# 查看卷
docker volume inspect todo-db
4.使用绑定挂载
使用绑定挂载,可以控制主机上的确切挂载点。可以使用它来持久化数据,但它通常用于向容器中提供额外的数据。在处理应用程序时,可以使用绑定挂载将源代码挂载到容器中,让它看到代码更改、响应,并让我们立即看到更改。
对于基于节点的应用程序,nodemon是监视文件更改然后重新启动应用程序的好工具。大多数其他语言和框架中都有等效的工具。
绑定挂载和命名卷是 Docker 引擎附带的两种主要卷类型。但是,可以使用其他卷驱动程序来支持其他用例(SFTP、Ceph、NetApp、S3等)。
命名卷 | 绑定挂载 | |
Host位置 | Docker 选择 | 自己控制 |
挂载示例 (using -v ) | my-volume:/usr/local/data | /path/to/data:/usr/local/data |
用容器内容填充新卷 | Yes | No |
支持卷驱动程序 | Yes | No |
4.1.启动一个开发模式容器
要运行我们的容器以支持开发工作流程,我们将执行以下操作:
- 将源代码挂载到容器中
- 安装所有依赖项,包括“dev”依赖项
- 启动 nodemon 以监视文件系统更改
# 1.确保您没有getting-started运行任何以前的容器。
# 2.从应用程序目录运行以下命令。
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
node:12-alpine \
sh -c "yarn install && yarn run dev"
# -dp 3000:3000 和之前一样。以分离(后台)模式运行并创建端口映射
# -w /app 设置“工作目录”或命令将运行的当前目录
# -v "$(pwd):/app" 将容器中主机的当前目录绑定挂载到/app目录中
# node:12-alpine 要使用的镜像。请注意,这是来自 Dockerfile 的应用程序的基础镜像
# sh -c "yarn install && yarn run dev"- 命令。使用sh启动一个 shell 并运行yarn install以安装所有依赖项,然后运行yarn run dev. 如果查看package.json,会看到dev脚本正在启动nodemon。
# 查看日志docker logs。
docker logs -f <container-id>
# 看完日志后,按Ctrl+退出C。
# 现在,对应用程序进行更改。
# 随意进行任何其他更改。完成后,停止容器并使用以下命令构建新镜像
docker build -t getting-started .
5.多容器应用
5.1.容器网络
默认情况下,容器是独立运行的,对同一台机器上的其他进程或容器一无所知。如何让一个容器与另一个容器通信呢?答案是 网络。
5.2.启动 MySQL
# 创建网络
docker network create todo-app
# 启动 MySQL 容器并将其连接到网络。
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
# 要确认我们已启动并运行数据库,请连接到数据库并验证它是否已连接。
docker exec -it <mysql-container-id> mysql -u root -p
5.3.连接到 MySQL
为了解决通信问题,我们将使用nicolaka/netshoot容器,它附带了许多对故障排除或调试网络问题很有用的工具。
# 使用 nicolaka/netshoot 镜像启动一个新容器。确保将其连接到同一网络。
docker run -it --network todo-app nicolaka/netshoot
# 在容器内部,我们将使用dig命令,这是一个有用的 DNS 工具。我们将查找主机名的 IP 地址mysql。
dig mysql
todo 应用程序支持设置一些环境变量来指定 MySQL 连接设置。他们是:
MYSQL_HOST
- 正在运行的 MySQL 服务器的主机名MYSQL_USER
- 用于连接的用户名MYSQL_PASSWORD
- 用于连接的密码MYSQL_DB
- 连接后使用的数据库
通过 Env Vars 设置连接设置
虽然使用 env vars 来设置连接设置对于开发来说通常是可以的,但 在生产中运行应用程序时,它是非常不受欢迎的。Docker 的前安全主管 Diogo Monica 写了一篇精彩的博客文章来 解释原因。
更安全的机制是使用容器编排框架提供的秘密支持。在大多数情况下,这些秘密作为文件挂载在正在运行的容器中。您会看到许多应用程序(包括 MySQL 映像和待办事项应用程序)也支持带有
_FILE
后缀的 env var,以指向包含变量的文件。例如,设置
MYSQL_PASSWORD_FILE
var 将导致应用程序使用引用文件的内容作为连接密码。Docker 没有做任何事情来支持这些环境变量。您的应用需要知道如何查找变量并获取文件内容。
# 注意:对于 MySQL 8.0 及更高版本,请确保在mysql
mysql> ALTER USER 'root' IDENTIFIED WITH mysql_native_password BY 'secret';
mysql> flush privileges;
# 指定上面的每个环境变量,并将容器连接到应用程序网络。
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"
# 查看容器 ( docker logs <container-id>) 的日志。
nodemon src/index.js
# 在浏览器中打开应用程序,然后将一些项目添加到待办事项列表中。
# 连接 mysql 数据库并证明项目正在写入数据库。记住,密码。
docker exec -it <mysql-container-id> mysql -p todos
mysql> select * from todo_items;
6.使用 Docker Compose
Docker Compose是一种用于帮助定义和共享多容器应用程序的工具。使用 Compose,可以创建一个 YAML 文件来定义服务,并且使用一个命令,可以启动所有内容或将其全部关闭。
使用 Compose的一大优势是可以在文件中定义应用程序堆栈,将其保存在项目 repo 的根目录中(它现在是版本控制的),并且可以轻松地让其他人为您的项目做出贡献。
6.1.安装 Docker Compose
如果为 Windows 或 Mac 安装了 Docker Desktop/Toolbox,那么已经拥有 Docker Compose!Play-with-Docker 实例也已经安装了 Docker Compose。如果在 Linux 机器上,则需要安装 Docker Compose。
查看版本信息 docker-compose version
6.2.创建 Compose 文件
1.在 app 项目的根目录下,创建一个名为docker-compose.yml
.
2.在撰写文件中,将从定义模式版本开始。在大多数情况下,最好使用支持的最新版本。可以查看 当前架构版本和兼容性矩阵的Compose 文件参考。
version: "3.7"
3.定义我们希望作为应用程序的一部分运行的服务(或容器)列表。
version: "3.7"
services:
6.3.定义应用服务
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.首先,为容器定义服务入口和镜像。可以为服务选择任何名称。该名称将自动成为网络别名,这在定义 MySQL 服务时会很有用。
version: "3.7"
services:
app:
image: node:12-alpine
2.通常,看到command
接近image
定义的内容,尽管没有要求。
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
3.通过定义服务来迁移-p 3000:3000
命令的一部分ports
。将在这里使用 短语法,但也有更详细 的长语法可用。
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
4.使用and定义迁移工作目录 ( -w /app
) 和卷映射 ( )。Volumes 也有短句和长句。-v "$(pwd):/app"working_dirvolumes
Docker Compose 卷定义的一个优点是可以使用当前目录的相对路径。
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
5.最后,使用environment
密钥迁移环境变量定义。
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
6.4.定义 MySQL 服务
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.首先定义新服务并为其命名,mysql
以便它自动获取网络别名。指定要使用的镜像。
version: "3.7"
services:
app:
# The app service definition
mysql:
image: mysql:5.7
2.将定义卷映射。当使用 docker run
运行容器时,会自动创建命名卷。但是,在使用 Compose 运行时不会发生这种情况。需要在顶层 volumes:
部分定义卷,然后在服务配置中指定挂载点。通过仅提供卷名,使用默认选项。不过,还有更多选择。
version: "3.7"
services:
app:
# The app service definition
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
volumes:
todo-mysql-data:
3.最后,需要指定环境变量
version: "3.7"
services:
app:
# The app service definition
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
此时,完成docker-compose.yml
:
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
6.5.运行应用程序
准备了docker-compose.yml
文件,就可以启动它了!
1.确保没有其他 app/db 副本首先运行(docker ps和docker rm -f <ids>)。
2.docker-compose up使用命令启动应用程序堆栈。将添加-d标志以在后台运行所有内容。
3.docker-compose logs -f 或 docker-compose logs -f app 使用命令查看日志。将看到每个服务的日志交错到一个流中。标志“-f”日志,因此会在生成时实时输出。
4.应该能够打开应用程序并看到它正在运行。
6.6.停止
docker-compose down
7.镜像构建最佳实践
7.1.安全扫描
docker scan
必须登录到 Docker Hub 才能扫描您的镜像。运行命令
docker scan --login
,然后使用docker scan <image-name>
.
扫描具体镜像
docker scan getting-started
7.2.镜像分层
docker image history --no-trunc APP
# --no-trunc 完整输出
7.3.图层缓存
Dockerfile
# syntax=docker/dockerfile:1
FROM node:12-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
回到镜像历史输出, Dockerfile 中的每个命令都成为镜像中的一个新层。当镜像更改时,必须重新安装 yarn 依赖项。有没有办法来解决这个问题?每次构建时都发布相同的依赖项没有多大意义,对吧?
为了解决这个问题,需要重新构建我们的 Dockerfile 以帮助支持依赖项的缓存。对于基于节点的应用程序,这些依赖项在package.json
文件中定义。那么,如果首先只复制该文件,安装依赖项,然后复制其他所有内容怎么办?
1.更新 Dockerfile 以package.json首先复制,安装依赖项,然后复制其他所有内容。
# syntax=docker/dockerfile:1
FROM node:12-alpine
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --production
COPY . .
CMD ["node", "src/index.js"]
2..dockerignore使用以下内容在与 Dockerfile 相同的文件夹中创建一个文件。
node_modules
.dockerignore
文件是一种有选择地仅复制镜像相关文件的简单方法。在此处阅读有关此内容的更多信息 。在这种情况下,node_modules
应在COPY
第二步中省略该文件夹,否则可能会覆盖由该RUN
步骤中的命令创建的文件。有关为何建议将其用于 Node.js 应用程序和其他最佳实践的更多详细信息,请查看关于 Dockerizing a Node.js Web 应用程序的指南。
3.使用docker build.
docker build -t getting-started .
4.对src/static/index.html文件进行更改。
5.docker build -t getting-started .现在再次使用构建 Docker 映像。
7.4.多阶段构建
多阶段构建是一个非常强大的工具,可以帮助使用多个阶段来创建图像。它们有几个优点:
- 将构建时依赖项与运行时依赖项分开
- 通过仅运送您的应用程序需要运行的内容来减小整体图像大小
更多推荐
所有评论(0)