Docker

官方文档:Dockerfile 参考 |Docker 文档

Linux安装

参考:Linux安装最新版Docker完整教程(建议收藏)_linux安装docker教程-CSDN博客

常见命令

🐳 常见命令

![截屏2024-05-04 19.07.15](/Users/tec/Library/Containers/me.damir.dropover-mac/Data/tmp/Screenshots/截屏2024-05-04 19.07.15.png)

🐳 关于 docker run

![截屏2024-05-04 19.08.00](/Users/tec/Library/Containers/me.damir.dropover-mac/Data/tmp/Screenshots/截屏2024-05-04 19.08.00.png)

🐳 一些命令的带参数使用

1
2
3
4
# -it 参数解释:进入容器后为了能够进行交互操作就需要一个命令行窗口 -it 参数就是为了打开一个可进行交互的命令行窗口
# bash 就是命令行
# 容器完全是隔离于外界的,独立的
docker exec -it <需要进入的容器名> bash
1
2
3
4
5
6
7
8
9
10
11
12
# 删除容器
docker rm <容器名>
# 但是必须要首先停止容器的运行
docker stop <容器名>
# 但是我们可以添加参数进行强行删除
docker rm <容器名> -f
# 删除容器镜像
docker rmi <镜像名>
# 查看成功启动的容器列表
docker ps
# 打印容器日志
docker logs <容器名>

🐳 具体详细命令查看官方文档

https://docs.docker.com/reference/dockerfile/

数据卷

🐳 案例一:利用Nginx容器部署静态资源
⚠️
所有的容器中准备的都是最小化的系统环境,只具备容器必须的使用的命令
⚠️ 为了能够解决上述问题,引入“数据卷”的概念

  • 案例需求
    • 常见Nginx容器,修改容器内部html目录下的index.html文件,查看变化
    • 将静态资源部署到nginx的html目录中
    • 寻找该目录我们可以在DockerHub中的Nginx详情中去找

🐳 数据卷基本知识

  • 这是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁
  • 这个目录只存在于逻辑中,现实中并不存在
  • 当容器中的目录与数据卷虚拟目录产生映射后,会在宿主机中创建一个对应的同名目录
    • 数据卷创建成功后,宿主机中的目录会和数据卷产生映射,数据卷再和容器目录产生映射。于是宿主机目录和容器目录产生简介映射
  • 宿主机目录或者是容器目录有任何一方产生改变,都会影响对方目录(双向映射)

🐳 实现案例一

  • 命令依旧是 docker run

  • 但是添加参数 -v 数据卷:容器内目录 这样就可以完成挂载数据卷

  • 当创建容器时候,如果挂载了数据卷但是数据卷不存在,那么就会自动创建数据卷

    • 也就是说不需要再使用 docker volume create 这个命令进行数据卷的创建
  • 使用这样的命令指定容器中的文件目录和本地文件夹进行映射(非数据卷挂载,目录挂载)

    1
    docker run -d --name nginx -p 80:80 -v /Users/yqc_forest/nginx-html:/usr/share/nginx/html nginx

    首先应该确保在我们本地中拥有这样的一个nginx-html文件夹(但是如果不存在是可以自动创建的好像),数据卷绑定成功后在文件夹中新建一个index.html文件,就可以实现与nginx容器中的index.html双向绑定,在修改了本地的index.html后,就可以同步修改nginx容器中的index.html。从而能够实现案例一

    ⚠️ 这时候我们的本地文件夹与nignx容器中的文件夹产生映射。当我在本地文件夹中添加内容时候,在容器中的文件夹同样可以读取到

  • ⚠️ ⚠️ 在使用 -v--mount 参数时,可以同时用于绑定挂载和卷

    1. 绑定挂载:当你指定的目的地路径是主机文件系统中的一个具体路径时,通常表示你在使用绑定挂载。例如:

      1
      2
      -v /host/path:/container/path

      在这种情况下,/host/path 是主机文件系统中的一个路径,它被挂载到容器中的 /container/path 路径上。

    2. :当你指定的目的地路径是一个不直接对应主机文件系统路径的名字时,通常表示你在使用卷。例如:

      1
      2
      -v volume_name:/container/path

      1
      2
      --mount source=volume_name,target=/container/path

      在这种情况下,volume_name 是一个卷的名称,它被挂载到容器中的 /container/path 路径上。卷的实际路径是由 Docker 管理的,一般位于宿主机的 /var/lib/docker/volumes 目录下,而不是直接映射到宿主机文件系统上的一个路径。

自定义镜像

🐳 关于镜像的定义
镜像就是包含了应用程序、程序运行的系统函数、运行配置等文件的文件包。构建镜像的过程其实就是把上述文件打包的过程

🐳 关于Dockerfile

![截屏2024-05-04 19.07.39](/Users/tec/Library/Containers/me.damir.dropover-mac/Data/tmp/Screenshots/截屏2024-05-04 19.07.39.png)

以上只是常用命令,详细命令和参考官方文档:https://docs.docker.com/engine/reference/builder

🐳 自定义镜像案例完整步骤实现

  • 新建一个文件夹存放我们的练习所需要的资料。包括tar包、Dockerfile以及jar包

  • cd 进入该文件夹,为了方便使用Dockerfile

  • 使用命将tar包上传到docker中成为本地镜像

    • docker load -i /Users/yqc_forest/DockerLocalImages/jdk.tar

    • 关于 docker load 后面两个可选参数的解释

      • docker load 命令用于从存档文件中加载镜像。它有两个可选参数:

        1. -input/-i:指定输入文件路径。你可以使用 i 参数指定要加载的存档文件的路径。如果不提供此参数,则 docker load 命令将从标准输入流中读取存档数据。

          例如:

          1
          docker load -i archive.tar
        2. -quiet/-q:静默模式。使用 q 参数可以使 docker load 命令在加载镜像时不输出详细的信息,只显示进度条。这在加载大型镜像时可能会减少输出。

          例如:

          1
          docker load -q -i archive.tar
  • 上传成功后可以使用 docker images 进行查看,确认本地镜像是否存在

  • 接着开始构建我们的自定义镜像,使用 docker build命令即可

    • 具体命令如下

      1
      docker build -t docker_demo .
  • 构建成功以后我们同样可以使用 docker images 命令去查看,确认是否已经存在镜像

  • 接着创建docker容器

    • 执行以下命令进行创建,容器取名为 dd

      1
      docker run -d --name dd -p 8080:8080 docker_demo
    • 运行后使用 docker ps 查看当前正在运行的 docker容器进程

  • 如果成功出现了 docker_demo的进程,那么我们可以查看进程运行日志

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    docker logs -f dd

    #出现了以下的输出信息
    . ____ _ __ _ _
    /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
    \\/ ___)| |_)| | | | | || (_| | ) ) ) )
    ' |____| .__|_| |_|_| |_\__, | / / / /
    =========|_|==============|___/=/_/_/_/
    :: Spring Boot :: (v2.7.12)

    17:50:24 INFO 1 --- [ main] com.itheima.mp.MpDemoApplication : Starting MpDemoApplication v0.0.1-SNAPSHOT using Java 11.0.16 on 53ee3e7bdb25 with PID 1 (/app.jar started by root in /)
    17:50:24 DEBUG 1 --- [ main] com.itheima.mp.MpDemoApplication : Running with Spring Boot v2.7.12, Spring v5.3.27
    17:50:24 INFO 1 --- [ main] com.itheima.mp.MpDemoApplication : No active profile set, falling back to 1 default profile: "default"
    17:50:25 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
    17:50:25 INFO 1 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
    17:50:25 INFO 1 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.75]
    17:50:25 INFO 1 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
    17:50:25 INFO 1 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 446 ms
    17:50:25 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
    17:50:25 INFO 1 --- [ main] com.itheima.mp.MpDemoApplication : Started MpDemoApplication in 0.888 seconds (JVM running for 1.057)
  • 接着可以去浏览器中访问 localhost:8080/hello/count。访问成功表示我们的自定义镜像构建成功,并在Docker中成功部署

🐳 总结

![截屏2024-05-04 19.07.50](/Users/tec/Library/Containers/me.damir.dropover-mac/Data/tmp/Screenshots/截屏2024-05-04 19.07.50.png)

网络

🐳 默认情况下,所有的容器都是以bridge方式连接到Docker的一个虚拟网桥上

🐳 自定义网络 → 加入自定义网络的容器才可以通过容器名相互访问
为了解决ip地址变更导致的连接到错误的容器问题

命令 说明
docker network create 创建一个网络
docker network ls 查看所有网络
docker network rm 删除指定网络
docker network prune 清除未使用的网络
docker network connect 使指定容器连接加入某网络
docker network disconnect 使指定容器连接离开某网络
docker network inspect 查看网络详细信息

项目部署

🐳 部署数据库
使用docker进行数据库的部署

部署后端项目

部署前端项目

实现了成功的访问(包括了后端的正常运行、前端网页的访问、数据库数据的正常读取)

Vue3部署

  1. 将vue的项目进行构建,输出dist

这个步骤就相当于是将vue的项目 npm run build 打包到服务器是一样的。

  1. 准备镜像内容dockerfile

dist目录之上新建一个dockerfile文件,该文件没有后缀,文件名即为此。然后输入如下内容:

1
2
3
4
5
6
7
8
9
10
11
# 使用nginx作为基础镜像
FROM nginx

# 移除默认的nginx配置文件
RUN rm /etc/nginx/conf.d/default.conf

# 将自定义的nginx配置文件添加到容器中的nginx配置目录中
ADD default.conf /etc/nginx/conf.d/

# 将dist目录下的静态文件复制到nginx默认的网站根目录
COPY dist/ /usr/share/nginx/html/
  1. 准备nginx配置default.conf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    server {
    listen 5173;
    server_name localhost;

    #charset koi8-r;

    #access_log logs/host.access.log main;

    location / {
    root /usr/share/nginx/html;
    index index.html;
    }
    location /admin {
    alias C:/wwwroot/42.192.90.134/admin;
    }
    location /api/ {
    # 后端的真实接口
    proxy_pass http://124.220.75.222:8080/;
    }
    location /tencent-api {
    # 后端的真实接口
    proxy_pass https://aiart.tencentcloudapi.com/;
    }
    location /tencent-download-api {
    # 后端的真实接口
    proxy_pass https://aiart-1258344699.cos.ap-guangzhou.myqcloud.com/text_to_img;
    }
    location /nginx_status {
    allow 127.0.0.1;
    deny all;
    stub_status on;
    access_log off;
    }
    }
  2. 制作镜像

1
2
3
4
5
docker build -t 镜像名字 .
# 比如:
docker build -t tecnb/nft .
# 下面为多平台进行部署,并且直接推送到dockerHub中
docker buildx build --platform linux/amd64,linux/arm64 -t tecnb/nft --push .

注意:后面的.不能省略,镜像创建成功之后使用docker images即可看到自己创建的镜像。

整个制作过程大概为1-5分钟。

制作镜像

  1. 启动镜像
1
2
docker run -d --name 镜像名字 -p 8888:80 vue3project
docker run -d -p 88:5173 --name nftContainer tecnb/nft

启动命令说明:

-d:容器在后台启动

—name : 镜像名称

-p 8888:80 :将nginx容器的80端口映射到主机的8888端口,我们访问时直接访问主机ip+映射到主机的端口,这里是8888,如果有路径,后面还要带上路径。 比如这里表示访问路径为:localhost:8888

tecnb/nft: 我们刚刚创建的自己的镜像的名称,在创建时就要规划好名字

注意:

你制作完镜像后,就可以在自己的docker desktop看到镜像,并且在那里直接配置访问端口和将镜像放置在容器中运行。

在桌面版看到制作好的镜像

容器:

docker 容器

至此,就相当于是将本地的vue的项目打包为一个docker镜像,并且可以在本地运行查看了,就像你部署到了一台虚拟服务器中!

  1. 发布到docker Hub库中

发布指令,其实很简单,直接在命令行输入如下命令即可:

1
2
docker push imqdcn/xxx:latest
# docker push 注册用户名/镜像名:tag名

意味着,你需要先注册和登录docker-desktop

登录

然后通过命令行,运行docer login 登录,看是否命令行也已经登录成功:

命令行登录

如果你的镜像名字在最开始时没起好名或与其他人发布的镜像名有冲突,可以通过如下方式改名:

1
2
3
docker tag xxx tecnb/xxx

# 表示将xxx改名为 tecnb/xxx,你也可以改为任意你喜欢的名字,比如tecnb/vue3project

以上都完成,就可以使用 第一条发布指令进行发布了。

docker-push发布

你可以在docker-desktop通过搜索该镜像名字找到镜像地址,或打开https://hub.docker.com/查找你发布的镜像:

搜索发布的镜像

  1. 发布后,其他人如何下载和运行呢?

镜像作者发给你hub镜像地址后,上面有拉取指令:

可以在命令行中先通过执行 docker pull下载到本地:

1
2
3
4
5
6
7
docker pull tecnb/xxx
# 如果后面没有写tagname,则使用默认的tagName:latest

# 下面为指定平台的写法
docker pull --platform linux/amd64 tecnb/nft
# 如果不确定平台的话可以使用下面的命令
uname -m

运行以上指令,即可在docker desktop看到该镜像,并可运行该镜像。

总结使用的命令,方便直接复制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 下面为多平台进行部署,并且直接推送到dockerHub中
docker buildx build --platform linux/amd64,linux/arm64 -t tecnb/nft --push .

# 删除原先的容器
docker rm nftContainer -f
# 删除容器镜像
docker rmi tecnb/nft

# 服务器端拉取最新的 amd64 平台的镜像
docker pull --platform linux/amd64 tecnb/nft
# 最后进行启动
docker run -d -p 88:5173 --name nftContainer tecnb/nft
# 查看成功启动的容器列表
docker ps
# 打印容器日志
docker logs nftContainer

Docker Compose

思路为直接将构建镜像相关的指令放在yml文件中,省去了在构筑多个镜像时的重复命令

现在看来好像是用来代替run命令的,上面的理解是错误的

安装

参考:解决Docker Compose下载报错问题-百度开发者中心 (baidu.com)Docker Compose (Docker) 撰写 |菜鸟教程 (runoob.com)

Linux 上我们可以从 Github 上下载它的二进制包来使用,最新发行的版本地址:https://github.com/docker/compose/releases。

运行以下命令以下载 Docker Compose 的当前稳定版本:

1
$ sudo curl -L "https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

将可执行权限应用于二进制文件:

1
$ sudo chmod +x /usr/local/bin/docker-compose

创建软链:

1
$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

测试是否安装成功:

1
2
$ docker-compose version
cker-compose version 1.24.1, build 4667896b

docker-compose.yml

这里之前使用81:81后面的端口乱填导致了一直无妨访问到网站,注意后面的端口是容器内部的端口号

而前面的”81”则是主机上的端口号。

这意味着当你访问主机的81端口时,Docker会将流量转发到容器内部的82端口,从而实现主机与容器之间的通信。

注意platform记得切换对应平台linux/amd64 linux/arm64

注意在使用命令前记得把之前的镜像进行删除,否则无法自动拉取到最新的进行到本地

1
2
3
4
5
6
7
8
9
10
11
12
13
14
services:
nftCompose:
image: tecnb/nft
ports:
- "81:5173"
platform: linux/amd64
container_name: nftCompose

nftAdminCompose:
image: tecnb/nftadmin
ports:
- "82:5173"
platform: linux/amd64
container_name: nftAdminCompose

命令

1
2
docker rm nftallcompose -f
docker-compose -p nftallcompose up -d

GitHub Actions(CI/CD)

思路为在提交仓库时,运行npm run build命令,然后将

WatchTower

思路为指定每隔多少时间就自动拉取一次镜像,当然可以设置比如说半分钟就拉一次,这样就不需要再手动进行拉取等工作,但是这样的设置会占据很多的带宽,所以可以设置较宽松的拉取时间,将其作为非调试阶段的自动更新,保证服务器端端代码是比较新的状态

以下是如何使用 Watchtower 实现自动更新的步骤:

  1. 快速启动 Watchtower:执行以下标准命令启动 Watchtower 容器,并每 5 分钟一次检查所有容器的镜像是否为最新版。如果发现镜像更新,Watchtower 会自动停止容器、删除容器、拉取最新镜像,然后使用之前启动容器的命令重新启动容器:docker run: 这是 Docker 命令行工具用于运行容器的命令。

    1
    docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower

    -d: 这是一个选项,表示在后台运行容器。

    --name watchtower: 这是为容器指定的名称,即容器的标识符。在这种情况下,容器的名称被设置为 “watchtower”。

    -v /var/run/docker.sock:/var/run/docker.sock: 这是一个数据卷选项,用于将 Docker 守护程序的 Unix 套接字(socket)文件挂载到容器内的同一路径。这种挂载允许容器与宿主机上的 Docker 守护程序进行通信,从而能够监控并更新其他容器。

    containrrr/watchtower: 这是要运行的 Docker 镜像的名称。在这里,使用的是一个名为 “watchtower” 的镜像,由 Containrrr 维护。这个镜像的作用是自动监控并更新其他容器的镜像,保持其最新状态。

    注意:这个命令默认更新所有运行中的容器,包括 Watchtower 自己。如果您只想更新指定的容器,请继续阅读下面的步骤。

  2. 指定更新容器:如果您不需要自动更新所有稳定运行的容器,可以配置仅更新指定的容器。首先,使用以下命令查看您 NAS 中运行的所有 Docker 容器的名字:

    1
    docker ps

    假设您需要监控并更新的容器为 librespeed-1portainer,您可以运行以下命令:

    1
    docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower librespeed-1 portainer

    这样,Watchtower 只会更新指定的容器,其他容器将不会被更新。

  3. 自动清除旧镜像:默认情况下,Watchtower 长期使用会堆积很多标签为 none 的旧镜像,占用磁盘空间。您可以在命令后面加上 --cleanup 参数,这样每次更新后都会自动删除旧的镜像:

    1
    docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower --cleanup

    XXXX 为指定容器名字。

  4. 指定更新频率:您可以配置更新的频率。有两种方式可供选择:

    • 设置更新时间间隔(单位为秒),加入的命令参数为

      1
      --interval

      。例如, “watchtower” 容器会每隔 3600 秒(1小时)检查一次:

      1
      docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower --cleanup --interval 3600
    • 设置定时检测,格式为 6 字段 Cron 表达式,加入的命令参数为

      1
      --schedule

      。例如,每天凌晨 3 点检查更新:

      1
      docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower --cleanup --schedule "0 0 3 * * *"

    XXXX 为指定容器名字。

  5. 前台模式(手动更新):前台模式运行的 Watchtower 是手动模式,即 Watchtower 运行一次后自动退出容器。这对于更新次数较少的容器非常有用。加入的命令参数为 --run-once。例如,检查更新 librespeed-1portainer 并更新后退出 Watchtower 容器:

    1
    docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower --cleanup --run-once

    XXXX 为指定容器名字。

最常用的命令为

1
2
3
4
5
6
# 这里为5分钟更新一次
docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower --cleanup
# 进行删除方便后续修改watchtower的配置
docker rm watchtower -f
# 修改为60分钟(3600秒)更新一次
docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower --cleanup --interval 3600

linux安装宝塔面板

Linux面板8.1.0万能安装脚本

1
if [ -f /usr/bin/curl ];then curl -sSO https://download.bt.cn/install/install_panel.sh;else wget -O install_panel.sh https://download.bt.cn/install/install_panel.sh;fi;bash install_panel.sh ed8484bec

学习步骤

  1. 通过 docker 将NFT部署到本地,正常访问

  2. 服务器实现docker部署NFT(通过ssh安装docker就行)

  3. 完成WatchTower设置

  4. 实现使用compose把admin与nft一起打包成镜像,并实现本地访问

  5. 实现使用compose把admin与nft一起打包成镜像,并实现远程服务器访问

  6. 使用 GitHub Actions 打包部署NFT

  7. 使用 GitHub Actions 通过 SSH 将打包后的NFT传到服务器中,实现访问

  8. 使用 GitHub Actions 创建NFT的 docker 并使用服务器进行部署

BUG

  1. 由于window配置docker不太具有可参考性于是重新选个linux服务器

  2. 尝试通过qemu-user-static解决WARNING: The requested image's platform (linux/arm64) does not match the detected host platform (linux/amd64/v4) and no specific platform was requested的bug,具体报错为启动后无妨访问网页,打开容器的logs后显示报错exec /docker-entrypoint.sh: no such file or directory
    解决方法:
    参考:x86架构机器上运行arm64 docker(跨平台构建 Docker 镜像)_宿主机x86运行arm的docker镜像 exec format error-CSDN博客

  3. 继续报错exec /docker-entrypoint.sh: permission denied,无法解决,尝试过增加权限,但是完全找不到/docker-entrypoint.sh的位置

  4. 决定采用buildx,但是使用命令docker buildx build --platform linux/amd64,linux/arm64 -t tecnb/nft --push .出现报错ERROR: Multi-platform build is not supported for the docker driver.,使用bootstrap插件解决
    解决方法:
    参考:linux - Docker - Cannot build multi-platform images with docker buildx - Stack Overflow主要还是Copilot问出来的

    这个错误是由于 Docker Buildx 不支持在 docker driver 下进行多平台构建。

    首先,让我们检查一下您的 Docker Buildx 配置。您可以运行以下命令来查看当前的配置:

    1
    docker buildx inspect

    如果您的配置中没有包含多平台支持,您需要添加一个支持多平台构建的构建器。您可以使用以下命令创建一个新的构建器:

    1
    docker buildx create --use

    然后,您可以使用以下命令来设置多平台支持:

    1
    docker buildx inspect --bootstrap

    这将为您创建一个支持多平台构建的构建器,并将其设置为默认构建器。接下来,您应该能够使用 docker buildx build 命令进行多平台构建。

  5. 下载compose后使用docker-compose version后报错ERROR: Failed to Setup IP tables: Unable to enable SKIP DNAT rule: (iptables failed: iptables --wait -t nat -I DOCKER -i br-d19cbe8b08f9 -j RETURN: iptables: No chain/target/match by that name. (exit status 1))

    原因:在对 linux 的防火墙进行操作之后,需要重启 docker
    解决方法:
    参考:docker 启动或创建容器是报 Failed to Setup IP tables: Unable to enable SKIP DNAT rule 错误的的解决办法 - 被遗忘的优雅 - 博客园 (cnblogs.com)

    重启下就行

    1
    service docker restart