Docker
本文将从 Docker 的基础概念出发,介绍容器、镜像、Dockerfile、数据卷、网络和 Docker Compose 的常见用法。通过实际示例,带你理解如何构建镜像、运行容器、挂载目录、暴露端口以及编排多服务应用,帮助开发者快速掌握 Docker 在本地开发、服务部署和环境隔离中的基本实践。
1.快速入门
推荐教程:https://docker.easydoc.net/doc/81170005/cCewZWoN/lTKfePfP
https://docs.docker.com/engine/reference/builder/
https://docs.docker.com/compose/compose-file/
1.1开始使用
- 启动教程
docker run -dp 80:80 docker/getting-started
// -d 后台运行
// -p hostPort:containerPort 映射端口
1.2一个简单的应用例子
-
下载地址:https://github.com/docker/getting-started/archive/refs/heads/master.zip
-
解压其中的app文件夹
-
在app文件夹目录中创建Dockerfile
FROM node:12-alpine RUN apk add --no-cache python2 g++ make WORKDIR /app COPY . . RUN yarn install --production CMD ["node","src/index"] EXPOSE 3000 -
构建docker镜像
docker build -t getting-started . # 镜像名:getting-started # Dockerfile路径:. -
启动容器
docker run -dp 3000:3000 getting-started -
改动容器内源码重新编译
-
查看正在所有容器
docker ps -
停止容器
docker stop containerId -
删除容器
docker rm containerId强制删除正在运行容器:
docker rm -f containerId -
登录到docker
docker login -u YOUR-USER-NAME. -
使用tags创建相同镜像的不同名称
docker tag getting-started YOUR-USER-NAME/getting-started -
共享文件系统(挂载卷)
docker volume create 卷名 # docker会自动创建命名卷,无需手动创建 docker run -dp hostPort:containerPort -v 卷名:挂载路径(例:/etc/todo) 镜像名 # docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started查看共享文件系统位置:
docker volume inspect 卷名 -
创建网络
docker network create todo-app -
启动数据库连接到网络
powerShell:
# 其中network选项相当于虚拟网卡名,network-alias相当于该局域网内此应用的域名 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.7mysql 8.0以后需要执行以下命令:
mysql -u root -p secret # 进入mysql alter user "root" identified with mysql_native_password by "secret"; flush privileges;注:docker会自动创建命名卷,无需手动创建
-
查看network-alias为mysql的ip地址
docker run -it --network todo-app nicolaka/netshoot # 启动网络检查工具 dig mysql -
连接app到mysql
PS> 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-compose
docker-compose version-
创建docker-compose.yml
version: "3.7" services: # 服务名将默认为network-alias(会自动创建网络) 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 volumes: - todo-mysql-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: todos volumes: todo-mysql-data: -
启动应用
docker-compose up -d -
跟踪日志
docker-compose logs -f app -
停止应用
docker-compose down docker-compose down --volumes # 删除卷
-
-
检查安装的文件版本是否有漏洞
docker scan --login <image-name> -
使用layer缓存
- 修改dockerfile
# syntax=docker/dockerfile:1 FROM node:12-alpine RUN apk add --no-cache python2 g++ make WORKDIR /app # 先安装依赖,如果没有变化,将会使用缓存 COPY package.json yarn.lock ./ RUN yarn install --production # 再复制其他文件 COPY . . CMD ["node", "src/index.js"]-
创建.dockerignore
此文件会使docker在COPY时忽略这些文件
node_modules
1.3开发环境映射本机文件到容器进行开发
PS> docker run -dp 3000:3000 `
-w /app -v "$(pwd):/app" `
node:12-alpine `
sh -c "yarn install && yarn run dev"
1.4查看docker日志
docker logs -f <container-id>
2.Dockerfile
2.1简介
Dockerfile:用于构建应用的文件
.dockerignore:使用COPY命令时,忽略的文件夹
2.2构建
docker build -f /path/to/a/Dockerfile . # 以指定Dockerfile构建
docker build -t shykes/myapp . # 以指定仓库名和tag构建
2.3Parser directives
用于控制docker编译器的参数,必须放置在Dockerfile的最前面
# directive=value
FROM ImageName
# unknowndirective=value
# knowndirective=value 此处将被视为注释
可用parser directives:
# 新版docker默认启动
# syntax=[remote image reference]
# syntax=docker/dockerfile:1
# syntax=docker.io/docker/dockerfile:1
# syntax=example.com/user/repo:tag@sha256:abcdef...
2.4escape
windows下推荐使用(指定自定义命令换行符,默认为\):
# escape=`
2.5ENV
注:该环境变量会写入镜像中,若不想写入,只想在构建阶段使用,推荐使用ARG
ENV abc=bye def=${abc} # 环境变量定义,通过${}引用
支持的命令:
ADD
COPY
ENV
EXPOSE
FROM
LABEL
STOPSIGNAL
USER
VOLUME
WORKDIR
ONBUILD
2.6FROM
语法:FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
[AS <name>]用法:在多个FROM之间COPY文件(COPY --from=<name>)
[--platform=<platform>]:linux/amd64,linux/arm64, `windows/amd64,$BUILDPLATFORM
FROM and ARG配合:
ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app
FROM extras:${CODE_VERSION}
CMD /code/run-extras
2.7RUN
用法:
RUN <command> # command run in shell, /bin/sh -c on Linux or cmd /S /C on Windows
RUN ["executable", "param1", "param2"]
2.8CMD
CMD ["executable","param1","param2"] (exec form, this is the preferred form)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (shell form)
与ENTRYPOINTS的区别:CMD可以被docker run的参数覆盖
2.9LABEL
镜像标签
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
查看标签:
docker image inspect --format='' myimage
2.10EXPOSE
只能当作文档提供给别人(docker run -P会暴露这些端口到随机的外部端口)
EXPOSE <port> [<port>/<protocol>...] # 默认协议为TCP
实际暴露方法:
docker run -p 80:80/tcp -p 80:80/udp ...
2.11ADD
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
ADD [--keep-git-dir=<boolean>] <git ref> <dir> # keep-git-dir表示.git是否包含
ADD --keep-git-dir=true https://github.com/moby/buildkit.git#v0.10.1 /buildkit
ADD git@git.example.com:foo/bar.git /bar
2.12COPY
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
2.13WORKDIR
WORKDIR /a
WORKDIR b # 相对于上一个路径
WORKDIR c
RUN pwd
2.14SHELL
切换当前shell
SHELL ["executable", "parameters"]
2.15Here-Document
# syntax=docker/dockerfile:1
FROM python:3.6
RUN <<EOT
#!/usr/bin/env python
print("hello world")
EOT
3.配置容器代理
启动容器时自动设置
~/.docker/config.json:
{
"proxies":
{
"default":
{
"httpProxy": "http://192.168.1.12:3128",
"httpsProxy": "http://192.168.1.12:3128",
"noProxy": "*.test.example.com,.example2.com,127.0.0.0/8"
}
}
}