docker 容器

运行 nginx 容器,运行时,先看本地有没有,有的话,直接运行本地,反之从远程拉取后再运行

docker run -d nginx:latest

查看容器的信息(inspect)

docker inspect container_id

进入到名字为 c1 的容器,打开其 bash 进行操作。-i 提供交互式、-t 提供终端(run)

docker run -i -t --name container_name centos:latest bash

简写

docker run -it --name container_name centos:latest bash

退出终端: ctrl+p+q 只是退出终端,但是让容器还可以运行 彻底退出: exit bash 直接关闭容器命令,关闭后,容器自动停止

进入到容器 bash 内(推荐)

docker exec -it container_id /bin/bash

在指定的容器中运行命令,并获取结果(exec)

docker exec -it container_name <command (如:ifconfig)>

进入到正在运行的容器中进行操作(attach)

docker attach container_name

退出不停止容器,仍然是 ctrl+p+q 命令

查看正在运行的 docker 容器(ps)

docker ps

查看正在运行和已经停止的 docker 容器(所有容器)

docker ps --all

运行容器(start)

docker start container_name container_name2

停止运行容器(stop)

docker stop container_name container_name2

查看容器的运行进程信息-对应物理机的信息

docker top container_id

删除容器, 此命令只能先停止容器后再删除(rm)

docker rm container_name

批量删除容器

docker ps --all awk '{if(NR>=2){print $1}}' | xargs docker rm

导出容器, 将容器导出为 tar 包(不推荐使用,推荐使用:save 下面有示例)

docker export -o container-id.tar container_id

导入容器(不推荐使用,推荐使用:load 下面有示例)

docker import container-id.tar [container_name]:[tag]

Dockerfile 将当前项目打包为镜像(需要在执行目下包含 Dockerfile 文件)

docker build -t [image_name]:[version] .

docker 镜像

docker 镜像是有些是一层的,有些是多层的,可以再下载和删除的时候可以看到。 镜像下载的层,是可以被共享的(如: 当前本地存在一个镜像,是很多层的。随后再次下载镜像的时候, 里面包含的层,有本地存在镜像的层,那么存在的层,就不会被重新下载了)

docker images

tag: 用来发布版本的,镜像是不可变的,每次发布一个版本就是一个镜像,tag 用来标记当前的版本信息

查看镜像的保存位置

搜索 docker hub 镜像,模糊查找。也可以去官方的首页搜索镜像

docker search centos

拉取远程服务器镜像

docker pull image_name

拉取指定的版本镜像

docker pull image_name:x.x

镜像的删除, 如果镜像被使用了(容器中存在,不是停止),则无法删除,反之则可以删除

docker rmi image_name、docker rmi image_name:x.x

容器文件 io 操作并保存(镜像不可以读写,容器是可以读写的)

## 1. docker run -it container_name bash
## 2. 文件 io 操作命令
## 3. 容器只要不删除,那么容器内的数据仍然是存在的

在 commit 的时候,会基于当前的容器层,发布的为新的容器(它们之间共享了层)在删除时,需要注意

docker commit container_id [container_name]:[tag]

docker 将Dockerfile 打包为镜像

## 可以直接使用 docker build -t [container_name]:[tag] . 将本地的项目打包为 docker 镜像。然后直接使用 save -o 进行导出 tar 包。
## 但是,如果使用了 docker run -it [container_name]:[tag] /bin/bash 之后进入到镜像中操作了镜像,然后就可以使用 commit 提交镜像了。不需重新执行 build -t 打包
docker build -t [container_name]:[tag] .

## 打包为镜像后,docker image 就可以看到这个镜像了
docker images

## 将这个镜像运行为容器
docker run -d -p 8080:80 --name [自定义容器名称] [镜像名称]

将镜像导出为 tar 包,这样的话,其它机器直接就可以使用 docker 进行运行了(save)

docker save -o image-tar-name.tar container_name

将 docker 导出的镜像 tar 包进行加载

docker load -i image-tar-name.tar

load 后,将镜像进行端口映射并启动,-d:后台运行镜像、-p:端口映射

docker run -d -p [origin_port]:[target_port] [container_name]:[tag]

commit+save+load 的方式用的是比较多的,import 和 export 用的是比较少的,几乎不用

容器镜像加速器

容器镜像加速器配置文件(阿里云控制台搜索:容器镜像加速器, 镜像加速器是免费的,直接去控制台获取)

/etc/docker/daemon.json
systemctl daemon-reload
systemctl restart docker

docker 内部拷贝文件

若docker做了物理机的映射,那么在程序需要的文件或目录内,不要直接手动拷贝目录或文件,最好通过 docker cp 来操作。(文件或目录存在句柄,直接操作可能会不识别)

## 语法:docker cp <宿主机路径> <容器名>:<容器内部路径>
docker cp .\my-app\.next\static\. nextjs_site:/app/.next/static

dockerfile

FORM: 生成的镜像需要基于哪个镜像

LABEL:标签

RUN:构建镜像时,运行的 shell 命令,与 CMD 的本质区别是,CMD 是镜像完成创建后,而 RUN 是在创建镜像时。 RUN echo "hello"
在执行多条 RUN 的时候,需要使用 && 来进行命令的连接执行(docker 在执行 RUN 时,会对每一个 RUN 创建一个分层。)

COPY:拷贝文件(只能是容器内的文件,不能把宿主机的文件拷贝到容器中去)
COPY src dest
src 不能是一个 url 链接

ADD:添加文件或解压文件, 可以将宿主机的文件添加到容器内
ADD src dest
src 可以是一个 url 链接,当 src 为 url 链接时,那么就类似于 wget 命令先进行下载

ENV:设置环境变量
ENV MODE_ENV production

USER:运行命令的时候,指定的用户是哪个
USER root

EXPOSE:声明容器运行的服务端口(不是映射)将容器内运行的服务端口暴露出去
EXPOSE 8080 8000 3000

WORKDIR:命令运行的工作目录,类似 Node 的 spawn 运行工作目录 (不要使用 RUN 命令去执行类似: RUN cd /root)
WORKDIR /root

CMD:在容器内执行命令,如,容器内启动 nginx 等服务。(每个 dockerfile,只能有一条 cmd 命令,多条的话,将会执行最后一条, 可以执行 一个 sh 文件)。
CMD ifconfig

VOLUME: 把宿主机的目录与容器内的目录进行映射

如何使用 dockerfile 生成容器,在执行下面的这条命令时,在执行目录下需要存在 Dockerfile
生成成功后,本地就会多出这一个镜像
docker build -t [image_name]:[version]

优化制作的镜像

1. 将多个 run 命令进行合并。(需斟酌命令的执行顺序)
2. 清理废弃的缓存文件。
3. 多阶段构建镜像。

docker compose 修改后重新启动

## 1. 在docker-compose.yaml 的目录下执行如下命令,停止当前当前docker-compose.yaml 文件中配置的容器中,正在运行的容器
## 这个命令也会把容器删除,但是对于做了物理机映射的来说,是没关系的
docker-compose down

## ...执行更新操作

## 2. 重新执行镜像构建
## 需要增加 --build 参数,不增加的话,就只是启动镜像
docker-compose up -d --build

docker-compose 端口映射

## 在 docker-compose.yaml 文件中,port 是表明物理机与宿主机的端口映射配置

services:
  ## ...
  nginx-proxy-manager:
    image: 'jc21/nginx-proxy-manager:latest'
    ports:
      - '80:80'   ## 左侧是宿主机端口映射,右侧是容器内端口映射
      - '443:443'
      - '81:81'
    volumes:
      - ./npm/data:/data
      - ./npm/letsencrypt:/etc/letsencrypt
      - ./xxxx:/data/nextjs/static

net 桥接端口检查

## 在一个容器内,检查这个容器与另外一个容器的网络是否通畅 container_name 要是 docker-compose.yaml 中的 container_name
## 只能是 container_name,不能是路由名称

docker exec -it <container_name> sh -c "curl -I http://nextjs-app:3000"

docker 创建网络并在多实例中连接

## 先执行如下命令,在docker中创建一个网络
docker network create vanner-network

## 对应的docker容器加入此网络时,docker-compose.yaml 可以这么写
## 以下是 postgres 加入到这个网络的示例。
## 当加入后,其它的在docker内的后端服务器,需要访问时,就可以把host填写为:vanner-network 就可以访问到了

version: '3.8'

services:
  db:
    image: postgres:16-alpine
    container_name: postgres
    restart: always
    environment:
      POSTGRES_USER: root
      POSTGRES_PASSWORD: a19961028.
      POSTGRES_DB: 17memory
    volumes:
      - ./pgdata:/var/lib/postgresql/data
    networks:
      - vanner-network  # 加入公共网络

networks:
  vanner-network:
    external: true  # 🌟 关键:告诉 Docker 使用手动创建的外部网络

服务器不开放给端口,通过ssh桥接。

此方式适用:服务器未开放外网端口,本地又需要调试服务器端口时

  # 格式:ssh -L [本地端口]:[目标容器名或容器内IP]:[容器内映射端口] [服务器用户名]@[服务器IP]
  ssh -L 5433:[容器内的ip地址]:[容器内监听的端口] [target-server-login-username]@[target-server-ip]

看下同一个路由中,可访问的 host 主机有哪些

## 路由名称通过 docker network create 创建、但是要记得,把 docker-compose.yaml 中的 network 写上路由名称
docker network inspect [路由名称]