云计算:Docker 命令

常用命令

docker version
docker info
docker <命令> --help

# 镜像
docker login -u <用户名>
docker tag <镜像名> <用户名>/<镜像名>
docker images
docker push <用户名>/<镜像名>
docker run -dp <本机端口号>:<容器端口号> <用户名>/<镜像名>
docker rmi -f <image-id>
docker rmi -f $(docker images -aq)
docker image prune # 删除所有未被 tag 标记的虚悬镜像
docker search <镜像名> --filter=STARS=3000 # 搜索镜像,过滤出大于3000星的镜像
docker pull <镜像名>:<tag> # 下载镜像,不写 tag 默认下载 latest 版本

# 容器
docker run -d -p 80:80 --name <容器名> <镜像名> # `-d` - 以分离模式(在后台)运行容器
docker run -dp 80:80 --name <容器名> <镜像名> # `-p 80:80` - 将主机的80端口映射到容器的80端口(-p 为 -publish)
docker run -it <镜像名> /bin/bash # 进入交互式容器,退出命令为 exit,`Ctrl + P + Q` 为不停止退出交互式容器
docker exec -d <container-name/container-id> <命令> # 在容器后台运行命令
docker exec -it <container-name/container-id> /bin/bash # 进入容器后开启一个新的终端
docker attach --sig-proxy=false <container-name/container-id> # 进入容器正在执行的终端,不会启动新的进程
docker ps
docker ps -a
docker ps --all
docker start <container-name/container-id>
docker stop <container-name/container-id>
docker restart <container-name/container-id>
docker kill <container-name/container-id>
docker rm <container-id>
docker rm <container-id> <container-id> <container-id> <container-id>
docker rm -f <container-id> # 强制移除容器(包括正在运行的)
docker rm -f $(docker ps -aq) # 强制移除所有容器
docker top <container-id> # 查看容器进程信息
docker inspect <container-id> # 查看容器内部信息

# 文件拷贝
docker cp <container-id>:<容器中的文件> <拷贝到本机的目录> # 文件从容器拷贝到宿主机
docker cp <本机文件> <container-id>:<容器中的文件的目录> # 文件从宿主机拷贝到容器

# 命名卷
docker volume create <卷名>
docker volume list
docker run -dp <本机端口号>:<容器端口号> -v <卷名>:<容器中的挂载目录> <用户名>/<镜像名> # 自动创建指定的卷,默认存放路径 `/var/lib/docker/volumes/<卷名>/_data`
docker volume inspect <卷名> # 查看卷的详细信息

# 绑定挂载
docker run -dp 3000:3000 \
     -w /app \								# 设定「工作目录」或指令运行的工作目录
     -v "$(pwd):/app" \						# 将当前工作目录挂载到容器里面的`/app`目录
     node:12-alpine \						# 要使用的镜像及版本
     sh -c "yarn install && yarn run dev"	# 用 `sh -c` 开启一个 shell 执行字符串中的内容

# 通过日志来查看内部的执行信息,按 `Ctrl+C` 退出
docker logs -f <container-id>
docker logs -tf --tail 10 <container-id>

# 网络
docker network create <网络名>
docker network create -d bridge <网络名> # 创建一个桥接网络
docker network list

docker run -d \
     --network <网络名> \
     --network-alias <网络别名> \
     -v <卷名>:<容器中的挂载目录> \
     -e MYSQL_ROOT_PASSWORD=<root用户密码> \
     -e MYSQL_DATABASE=<数据库名> \
     mysql:5.7

docker exec -it <mysql-container-id> mysql -u root -p # 进入容器,并执行命令
docker run -it --network <网络名> nicolaka/netshoot # 用 DNS 工具查找主机名 mysql 的 IP 地址
dig mysql # 查找主机名 mysql 的 IP 地址,虽然 mysql 不是一个有效的主机名,但 Docker 可以将其解析为具有该网络别名的容器的 IP 地址

Dockerfile

Dockerfile 文件

# syntax=docker/dockerfile:1
# 指向版本1语法的最新版本,在构建之前自动检查语法更新,确保您使用的是最新版本。必须始终位于 Dockerfile 的顶部。
# 文件中的注释以 `#` 符号开头,并且必须在一行的开头。

ARG IMAGE_NAME=<镜像名> # 相当于定义变量,在多阶段构建时根据阶段区分作用域,写在 FROM 外面为全局变量

##
## Build
##
FROM ${IMAGE_NAME} as <镜像别名>

# 用来给镜像以键值对的形式添加一些元数据(metadata),还可以用一些标签来申明镜像的作者、文档地址等
LABEL

ENV <环境变量名>=<环境变量值>
WORKDIR <指定的根目录/命令执行的位置>
# ADD 在 COPY 基础上增加了一些功能,这个功能其实并不实用,而且不推荐使用
# 所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD
COPY <本地文件名> <本地文件名> <拷贝到镜像中以 WORKDIR 为根的目录>
RUN <构建时运行的命令>
CMD ["<命令1>", "<命令2>", "<命令3>"] # 指定从此镜像启动容器时运行的默认命令

##
## Deploy
##
FROM <镜像名> as <镜像别名>
WORKDIR <指定的根目录/命令执行的位置>
COPY --from=<上阶段的镜像别名/可用0代替> <上阶段构建好的文件及路径> <移入本阶段的镜像中以 WORKDIR 为根的目录>

# 在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;
# 另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
# EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射
EXPOSE <暴露的端口号>

# 指定 RUN, CMD, ENTRYPOINT 这类命令的身份
USER <用户身份/用户名>

# 入口点,当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令
ENTRYPOINT ["<命令>"]
CMD ["<参数1>", "<参数2>", "<参数3>"]

命令

docker build --tag docker-gs-ping:latest . 								# :latest 可以省略不写,默认为 latest
docker image tag docker-gs-ping:latest docker-gs-ping:v1.0 				# image 可以省略
docker build -t docker-gs-ping:multistage -f Dockerfile.multistage .	# -f 指定自定义的 Dockerfile 文件名

Docker Compose

docker run -dp 3000:3000 \
   -w /app \
   -v "$(pwd):/app" \
   --network todo-app \
   -e MYSQL_HOST=mysql \
   -e MYSQL_USER=root \
   -e MYSQL_PASSWORD=123456 \
   -e MYSQL_DB=todos \
   node:12-alpine \
   sh -c "yarn install && yarn run dev"

docker-compose.yml

version: "3.7"

services:
  app:													# 服务名
    image: node:12-alpine								# 镜像名
    command: sh -c "yarn install && yarn run dev"		# 用 `sh -c` 开启一个 shell 执行字符串中的内容
    ports:
      - 3000:3000
    working_dir: /app									# 等同于上面的 (-w /app)
    volumes:											# 等同于上面的 (-v "$(pwd):/app")
      - ./:/app											# Docker Compose 卷的优点是可以使用 当前目录的相对路径
    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: 123456
      MYSQL_DATABASE: todos

volumes:				# Compose 运行时不会自动创建指定的卷,需要在 top-level volumes 中定义卷,然后在服务配置中指定挂载点。
  todo-mysql-data:		# 只需提供卷名,将使用默认选项

默认情况下,Docker Compose 会自动为应用程序堆栈创建一个网络(这就是为什么我们没有在 Compose 文件中定义一个网络)。

docker-compose up -d
docker-compose up --build -d # 如果不提供 --build 标志,源代码的更新不触发重新生成
docker-compose logs -f
docker-compose logs -f app	# 查看特定服务的日志
docker-compose config
docker-compose stop
docker-compose down # 默认情况下,在文件中的已命名卷不会被删除。如果要删除卷,则需要添加 --volume 标志

安全

docker scan --login
docker scan <镜像名>

镜像分层

docker image history getting-started
docker image history --no-trunc getting-started

应用示例

Dockerfile

下载一个demo:https://github.com/docker/getting-started/tree/master/app

Dockerfile

# syntax=docker/dockerfile:1
FROM node:12-alpine
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --production
COPY . .
EXPOSE 3000
CMD ["node", "src/index.js"] # CMD 指令指定从此图像启动容器时运行的默认命令

.dockerignore

在这种情况下,应该在第二个 COPY 步骤中省略 node_modules 文件夹,因为它可能会覆盖 RUN 步骤中命令创建的文件。

node_modules
# 构建镜像
docker build -t <镜像名> .

多阶段构建

# syntax=docker/dockerfile:1
FROM maven AS build
WORKDIR /app
COPY . .
RUN mvn package

FROM tomcat
COPY --from=build /app/target/file.war /usr/local/tomcat/webapps 
# syntax=docker/dockerfile:1
FROM node:12 AS build
WORKDIR /app
COPY package* yarn.lock ./
RUN yarn install
COPY public ./public
COPY src ./src
RUN yarn run build

FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html

克隆项目

git clone https://github.com/olliefr/docker-gs-ping

dockerfile.multigrade

# syntax=docker/dockerfile:1
# 指向版本1语法的最新版本,在构建之前自动检查语法更新,确保您使用的是最新版本。必须始终位于 Dockerfile 的顶部。
# 文件中的注释以 `#` 符号开头,并且必须在一行的开头。

##
## Build
##
# 指定应用程序使用的基础镜像
FROM golang:alpine AS builder

LABEL maintainer="toki@toki-plus@qq.com" \
      version="v1.0" \
      description="描述信息" \
      date="2022-04-11"

ENV CGO_ENABLED 0
ENV GOOS linux
ENV GOARCH amd64

# 指示 Docker 使用此目录作为所有后续命令的执行位置
WORKDIR /app

# 将 `go.mod` 和 `go.sum` 文件复制到镜像的 /app 目录中
COPY go.mod go.sum ./

# 设置 go 的初始环境变量,下载 mod 依赖
RUN go env -w GO111MODULE=on \
    && go env -w GOPROXY=https://goproxy.cn,direct \
    && go mod download \
    && go mod verify

# 将 go 后缀的文件移入镜像
COPY *.go ./

# 编译可执行文件,去掉了调试信息 -ldflags="-s -w" 以减小镜像尺寸
RUN go build -ldflags="-s -w" -o /docker-gs-ping

##
## Deploy
##
# 引用小型操作系统
FROM alpine:latest as deployer

# 使用 Alpine 基础镜像,安装软件包时需要用 apk 包管理器
RUN apk update --no-cache && apk add --no-cache ca-certificates tzdata
ENV TZ Asia/Shanghai

WORKDIR /

# 继承上一阶段的 builder 镜像,并拷贝生成的可执行文件
COPY --from=builder /docker-gs-ping /docker-gs-ping

# 暴露端口
EXPOSE 8080

USER nonroot:nonroot

# 入口点
ENTRYPOINT ["/docker-gs-ping"]

-t 为镜像添加标签,例如 <镜像名:版本号>

-f 指定自定义的 Dockerfile 文件名,默认的文件名为 Dockerfile

最后的 . 表示 Dockerfile 所在的位置

docker build -t docker-gs-ping:multistage -f Dockerfile.multistage .
docker run --publish 8080:8080 docker-gs-ping

打开新的命令行

curl http://localhost:8080/

已分离模式运行

docker run -d -p 8080:8080 --name rest-server docker-gs-ping

curl http://localhost:8080/

储存

# 创建卷
docker volume create roach

# 查看卷
docker volume list

网络

# 创建一个桥接网络
docker network create -d bridge mynet

# 查看网络
docker network list

启动数据库引擎

docker run -d \
  --name roach \
  --hostname db \
  --network mynet \
  -p 26257:26257 \
  -p 8080:8080 \
  -v roach:/cockroach/cockroach-data \
  cockroachdb/cockroach:latest-v20.1 \
  start-single-node --insecure

配置数据库引擎

docker exec -it roach ./cockroach sql --insecure
CREATE DATABASE mydb;
CREATE USER totoro;
GRANT ALL ON DATABASE mydb TO totoro;

quit

示例应用

git clone https://github.com/olliefr/docker-gs-ping-roach.git

docker build --tag docker-gs-ping-roach .

docker run -it --rm -d \
  --network mynet \
  --name rest-server \
  -p 80:8080 \
  -e PGUSER=totoro \
  -e PGPASSWORD=myfriend \
  -e PGHOST=db \
  -e PGPORT=26257 \
  -e PGDATABASE=mydb \
  docker-gs-ping-roach
  
curl localhost
# 或 curl http://localhost/

curl --request POST \
  --url http://localhost/send \
  --header 'content-type: application/json' \
  --data '{"value": "Hello, Docker!"}'
docker container stop rest-server roach
docker container rm rest-server roach
docker container list --all
docker run -d \
  --name roach \
  --hostname db \
  --network mynet \
  -p 26257:26257 \
  -p 8080:8080 \
  -v roach:/cockroach/cockroach-data \
  cockroachdb/cockroach:latest-v20.1 start-single-node \
  --insecure
  
docker run -it --rm -d \
  --network mynet \
  --name rest-server \
  -p 80:8080 \
  -e PGUSER=totoro \
  -e PGPASSWORD=myfriend \
  -e PGHOST=db \
  -e PGPORT=26257 \
  -e PGDATABASE=mydb \
  docker-gs-ping-roach

curl localhost
docker container list

Docker Compose

docker-compose.yml

version: '3.8'

services:
  docker-gs-ping-roach:
    depends_on: 
      - roach
    build:
      context: .
    container_name: rest-server
    hostname: rest-server
    networks:
      - mynet
    ports:
      - 80:8080
    environment:
      - PGUSER=${PGUSER:-totoro}
      - PGPASSWORD=${PGPASSWORD:?database password not set}
      - PGHOST=${PGHOST:-db}
      - PGPORT=${PGPORT:-26257}
      - PGDATABASE=${PGDATABASE:-mydb}
    deploy:
      restart_policy:
        condition: on-failure
  roach:
    image: cockroachdb/cockroach:latest-v20.1
    container_name: roach
    hostname: db
    networks:
      - mynet
    ports:
      - 26257:26257
      - 8080:8080
    volumes:
      - roach:/cockroach/cockroach-data
    command: start-single-node --insecure

volumes:
  roach:

networks:
  mynet:
    driver: bridge

docker compose 将自动从 .env 文件中读取环境变量。由于 Compose 文件要求设置 PGPASSWORD,因此我们将以下内容添加到 .env 文件

PGPASSWORD=whatever
docker-compose config
docker-compose up --build -d
docker exec -it roach ./cockroach sql --insecure
curl http://localhost/
docker-compose stop
docker-compose down
posted @ 2022-04-15 00:02  toki-plus  阅读(72)  评论(0编辑  收藏  举报