Docker笔记

学习了神光大佬的《Nest 通关秘籍》后,对docker做了个笔记,并实操部署了一下个人项目,在此记录一下

是什么

Docker是一种开源的容器化平台,它可以将应用程序及其依赖项打包到一个可移植的容器中,使得应用程序能够在任何地方以相同的方式运行。Docker容器可以在多种操作系统上运行,并且可以在云计算、物联网等各种场景下使用。Docker的出现,使得应用程序的开发、测试、部署等过程更加便捷、快速和可靠。

它把系统的所有文件封装成一个镜像,镜像跑起来作为容器,它可以在一台机器上跑多个容器,每个容器都有独立的操作系统环境,比如文件系统、网络端口等,在容器内跑各种服务。

这样整个环境都保存在这个镜像里,部署多个实例只要通过这个镜像跑多个容器就行。

容器是一组用于隔离文件系统、CPU 资源、内存资源、系统权限等的各种轻量级方法。容器在很多意义上类似于虚拟机,但它们比虚拟机更高效,而安全性则往往低于虚拟机。

docker desktop

一款为Mac和Windows操作系统提供的桌面应用程序,它可以帮助用户快速地安装和配置Docker环境。Docker Desktop包含了Docker Engine、Docker CLI、Docker Compose、Docker Machine等核心工具,同时还提供了图形界面,帮助用户更加方便地管理和操作Docker容器和镜像。

官网下载地址

images 是镜像,containers 是镜像跑起来的容器

搜索并拉取一个远程的镜像(nginx)

启动服务

浏览器访问 http://localhost 就可以访问到

docker命令

  • docker pull
docker pull nginx:latest
docker pull node:16.7.0
  • docker run
docker run --name nginx-test2 -p 90:80 -v /Users/liuzepeng/Desktop/test:/usr/share/nginx/html -e KEY1=VALUE1 -d nginx:latest 
# docker run --name=容器名称 镜像名称
docker run --name=restart-test-container restart-test:first
# --restart=always 指定重启策略
# -d 后台运行
docker run -d --restart=always --name=restart-test-container2 restart-test:first

-p 是端口映射

-v 是指定数据卷挂载目录

-e 是指定环境变量

-d 是后台运行

docker run 会返回一个容器的 hash

  • docker ps

显示容器列表的,默认是运行中的

docker ps 

想显示全部的,可以加个 -a

  • docker images

获取镜像列表

docker images

  • docker exec

我们在容器的 terminal 里执行命令,对应的是 docker exec 命令

docker exec -it c9014aa1e6ad43e5900f8ca8df764401554c1a83e5b914a20b786c5c2c90c601 /bin/bash

-i 是 terminal 交互的方式运行

-t 是 tty 终端类型

然后指定容器 id 和 shell 类型,就可以交互的方式在容器内执行命令了。

exit 退出

  • docker logs

docker logs 容器id ---> 查看日志

  • docker inspect

docker inspect 容器id ---> 容器详情

  • docker volume

管理数据卷

  • docker start:启动一个已经停止的容器
  • docker rm:删除一个容器
  • docker stop:停止一个容器

其他

来自chatgpt

当谈及 Docker 命令时,以下是一些常用且详细的 Docker 命令的总结:

镜像操作:

  • docker images:列出已下载的镜像。
  • docker pull <image>:从 Docker Hub 或其他 Registry 拉取指定的镜像。
  • docker build -t <name:tag> .:使用 Dockerfile 构建镜像,为其命名和标记。
  • docker rmi <image>:删除指定的镜像。
  • docker tag <source_image> <target_image>:给镜像打标签。

容器生命周期管理:

  • docker run <image>:创建并启动一个容器。
  • docker start <container>:启动已停止的容器。
  • docker stop <container>:停止正在运行的容器。
  • docker restart <container>:重启容器。
  • docker rm <container>:删除指定的容器。
  • docker ps:列出当前正在运行的容器。
  • docker logs <container>:查看容器日志。

容器操作和交互:

  • docker exec <container> <command>:在正在运行的容器中执行指定的命令。
  • docker attach <container>:附加到运行中的容器,即进入容器终端。
  • docker cp <local_path> <container>:<container_path>:将文件从主机复制到容器内。
  • docker cp <container>:<container_path> <local_path>:将文件从容器复制到主机内。

网络操作:

  • docker network ls:列出现有的 Docker 网络。
  • docker network create <name>:创建一个 Docker 网络。
  • docker network connect <network> <container>:将容器连接到指定的网络。
  • docker network disconnect <network> <container>:从指定的网络中断容器的连接。

Docker Compose:

  • docker-compose up:根据 docker-compose.yml 配置文件启动容器。
  • docker-compose down:停止并移除由 Docker Compose 启动的容器。

这些命令涵盖了 Docker 中常见的操作。然而,Docker 提供了更多功能丰富的命令和选项,可以根据具体需求进行进一步探索和学习。

如何制作镜像

Dockerfile

FROM node:latestWORKDIR /appCOPY . .RUN npm config set registry https://registry.npm.taobao.orgRUN npm install -g http-serverEXPOSE 8080CMD ["http-server", "-p", "8080"]
  • FROM:基于一个基础镜像来修改 先通过 FROM 继承了 node 基础镜像,里面就有 npm、node 这些命令
  • WORKDIR:指定当前工作目录
  • COPY:把容器外的内容复制到容器内 通过 COPY 把 Dockerfile 同级目录下的内容复制到容器内,这里的 . 也就是 /app 目录

COPY . . 是 Dockerfile 中的一条指令,用于将当前目录下的所有文件和文件夹复制到容器的工作目录(WORKDIR)中

  • EXPOSE:声明当前容器要访问的网络端口,比如这里起服务会用到 8080
  • RUN:在容器内执行命令 通过 RUN 执行 npm install,全局安装 http-server
  • CMD:容器启动的时候执行的命令 这里就是执行 http-server 把服务跑起来

创建如下文件

执行build

docker build -t aaa:ccc

aaa 是镜像名,ccc 是镜像的标签

docker build -t name:tag -f filename .
  • docker build:启动 Docker 构建过程。
  • -t name:tag:指定构建生成的镜像的名称和标签。name 是镜像的名称,tag 是镜像的标签,通常用于版本控制。
  • -f filename:指定 Dockerfile 文件的路径和名称,用于告诉 Docker 使用哪个 Dockerfile 进行构建。filename 是 Dockerfile 的路径和名称。
  • .:表示当前目录,也就是 Dockerfile 所在的目录。Docker 在构建过程中会将当前目录下的文件复制到镜像中。

减小镜像体积

镜像自然是越小性能越好,所以 docker 支持你通过 .dockerignore 声明哪些不需要发送给 docker daemon。

.dockerignore 是这样写的:

*.md
!README.md
node_modules/
[a-c].txt
.git/
.DS_Store
.vscode/
.dockerignore
.eslintignore
.eslintrc
.prettierrc
.prettierignore

docker build 时,会先解析 .dockerignore,把该忽略的文件忽略掉,然后把剩余文件打包发送给 docker daemon 作为上下文来构建产生镜像。

多阶段构建

还有一种减小镜像体积的手段:多阶段构建

第一次构建出 dist 目录,第二次再构建出跑 dist/main.js 的镜像

# build stage
FROM node:18 as build-stageWORKDIR /appCOPY package.json .RUN npm config set registry https://registry.npmmirror.com/RUN npm installCOPY . .RUN npm run build# production stage
FROM node:18 as production-stageCOPY --from=build-stage /app/dist /app
COPY --from=build-stage /app/package.json /app/package.jsonWORKDIR /appRUN npm install --productionEXPOSE 3000CMD ["node", "/app/main.js"]

之前是

打包后,这时候 app 下就是有 dist 的文件、生产阶段的 node_modules、package.json 这些文件:

对比下镜像体积,明显看出有减小,少的就是 src、test、构建阶段的 node_modules 这些文件:

但现在镜像依然很大呀,那是因为我们用的基础的 linux 镜像比较大,可以换成 alpine 的,这是一个 linux 发行版,主打的就是一个体积小。

alpine 基础镜像

FROM node:18.0-alpine3.14 as build-stageWORKDIR /appCOPY package.json .RUN npm installCOPY . .RUN npm run build# production stage
FROM node:18.0-alpine3.14 as production-stageCOPY --from=build-stage /app/dist /app
COPY --from=build-stage /app/package.json /app/package.jsonWORKDIR /appRUN npm install --productionEXPOSE 3000CMD ["node", "/app/main.js"]

一般情况下,我们都会用多阶段构建 + alpine 基础镜像。

docker daemon

Docker Daemon(dockerd)是 Docker 引擎的核心组件之一。它是一个运行在后台的持续运行程序,负责管理和控制 Docker 容器和镜像的生命周期。

守护进程(Daemon)是一种在操作系统中以服务方式运行的进程。与普通的前台进程不同,守护进程通常在系统启动时就会初始化并一直运行,不依赖于用户的登录会话。守护进程在后台默默地工作,接受来自其他进程或用户的请求,并提供相应的服务。

对于 Docker Daemon 来说,它作为 Docker 引擎的后台进程,持续运行,等待来自 Docker 客户端的指令和请求。当使用命令行或其他工具与 Docker 交互时,实际上是与 Docker Daemon 进行通信。Docker Daemon 负责解析和执行这些命令,并控制容器的创建、启动、停止、删除等操作,同时也管理镜像的构建、拉取、推送等过程。

因此,Docker Daemon 可以看作是 Docker 引擎的后台服务进程,它提供了对 Docker 容器和镜像的管理和控制能力,并在后台持续运行以提供服务。

docker

容器和宿主机还是有关联的,比如可以把宿主机的端口映射到容器内的端口、宿主机某个目录挂载到容器内的目录

比如映射了 3000 端口,那容器内 3000 端口的服务,就可以在宿主机的 3000 端口访问了。

比如挂载了 /aaa 到容器的 /bbb/ccc,那容器内读写 /bbb/ccc 目录的时候,改的就是宿主机的 /aaa 目录,反过来,改宿主机 /aaa 目录,容器内的 /bbb/ccc 也会改,这俩同一个。

这分别叫做端口映射、数据卷(volume)挂载。

运行镜像

docker run image-name
docker run -p 3000:3000 -v /aaa:/bbb/ccc --name xxx-container xxx-image

通过 xxx-image 镜像跑起来一个叫做 xxx-container 的容器。

-p 指定端口映射,映射宿主机的 3000 到容器的 3000 端口。

-v 指定数据卷挂载,挂载宿主机的 /aaa 到容器的 /bbb/ccc 目录。

这个镜像是通过 Dockerfile 经过 build 产生的。

过程

docker容器间通信

Docker 通过 Namespace 的机制实现了容器的隔离,其中就包括 Network Namespace。

因为每个容器都有独立的 Network Namespace,所以不能直接通过端口访问其他容器的服务。

那如果这个 Network Namespace 不只包括一个 Docker 容器呢??

可以创建一个 Network Namespace,然后设置到多个 Docker 容器,这样这些容器就在一个 Namespace 下了,就可以直接访问对应端口

Docker 确实支持这种方式,叫做桥接网络。

桥接网络

通过 docker network create 创建一个桥接网络,

docker network create common-network

然后把之前的 3 个容器停掉、删除,我们重新跑:

docker stop mysql-container redis-container nest-container
docker rm mysql-container redis-container nest-container

然后 docker run 的时候指定 --network 为我们刚创建的 common-network,这样 3 个容器就可以通过容器名互相访问了。

docker run -d --network common-network -v /Users/guang/mysql-data:/var/lib/mysql --name mysql-container mysql

在 docker-compose.yml 配置下 networks 创建桥接网络,然后添加到不同的 service 上即可。

version: '3.8'
services:nest-app:build:context: ./dockerfile: ./Dockerfiledepends_on:- mysql-container- redis-containerports:- '3000:3000'networks:- common-networkmysql-container:image: mysqlvolumes:- /Users/guang/mysql-data:/var/lib/mysqlnetworks:- common-networkredis-container:image: redisvolumes:- /Users/guang/aaa:/datanetworks:- common-network
networks:common-network:driver: bridge

实现原理就是对 Network Namespace 的处理,本来是 3个独立的 Namespace,当指定了 network 桥接网络,就可以在 Namespace 下访问别的 Namespace 了。

多个容器之间的通信方式,用桥接网络是最简便的。

docker和pm2重启策略

其实 PM2 诞生的时候是没有 Docker 这种容器技术的,那时候都是直接部署在机器上,这时候自然需要一个进程管理工具来做进程的重启、负载均衡等功能。这是 PM2 当年很流行的原因。

但后来有了 Docker,里面跑的进程崩溃之后,Docker 容器支持自动重启。

Docker 是支持自动重启的,可以在 docker run 的时候通过 --restart 指定重启策略,或者 Docker Compose 配置文件里配置 restart。

有 4 种重启策略:

  • no: 容器退出不自动重启(默认值)
  • always:容器退出总是自动重启,除非 docker stop。
  • on-failure:容器非正常退出才自动重启,还可以指定重启次数,如 on-failure:5
  • unless-stopped:容器退出总是自动重启,除非 docker stop

重启策略为 always 的容器在 Docker Deamon 重启的时候容器也会重启,而 unless-stopped 的不会。

其实我们用 PM2 也是主要用它进程崩溃的时候重启的功能,而在有了 Docker 之后,用它的必要性就不大了。

当然,进程重启的速度肯定是比容器重启的速度快一些的,如果只是 Docker 部署,可以结合 pm2-runtime 来做进程的重启。

绝大多数情况下,直接用 Docker 跑 node 脚本就行,不需要 PM2。

优化Dockerfile技巧

Dockerfile 有挺多技巧:

  • 使用 alpine 的镜像,而不是默认的 linux 镜像,可以极大减小镜像体积,比如 node:18-alpine3.14 这种
  • 使用多阶段构建,比如一个阶段来执行 build,一个阶段把文件复制过去,跑起服务来,最后只保留最后一个阶段的镜像。这样使镜像内只保留运行需要的文件以及 dependencies。
  • 使用 ARG 增加构建灵活性,ARG 可以在 docker build 时通过 --build-arg xxx=yyy 传入,在 dockerfile 中生效,可以使构建过程更灵活。如果是想定义运行时可以访问的变量,可以通过 ENV 定义环境变量,值使用 ARG 传入。
  • CMD 和 ENTRYPOINT 都可以指定容器跑起来之后运行的命令,CMD 可以被覆盖,而 ENTRYPOINT 不可以,两者结合使用可以实现参数默认值的功能。
  • ADD 和 COPY 都可以复制文件到容器内,但是 ADD 处理 tar.gz 的时候,还会做一下解压。

灵活使用这些技巧,可以让你的 Dockerfile 更加灵活、性能更好。

其他:dockerfile 内换行使用 \

使用 alpine 镜像

上面👆

https://www.yuque.com/leyioliu-76kvf/salixq/szw7vv4htqewch72#P7EvB

使用多阶段构建

上面👆

https://www.yuque.com/leyioliu-76kvf/salixq/szw7vv4htqewch72#P7EvB

使用 ARG 增加构建灵活性

灵活使用 ARG,可以增加 dockerfile 的灵活性

使用 Docker 的 ARG 指令可以增加构建过程的灵活性,允许在构建镜像时传递参数。这样可以在构建过程中根据不同的需求动态地设置一些值。

下面是使用 ARG 指令增加构建灵活性的步骤:

  1. 在 Dockerfile 中使用 ARG 指令定义一个变量,并可选地指定默认值,例如:
ARG my_var=default_value
  1. 在 Dockerfile 的构建过程中,你可以通过引用这个变量来使用它,例如:
ENV MY_VAR=${my_var}

这里使用了 ENV 指令将 ARG 变量的值赋给环境变量 MY_VAR。

  1. 构建镜像时,可以通过 --build-arg 标志传递一个新的值给这个变量。例如,通过以下命令构建镜像并传递一个新的值给 ARG 变量:
docker build --build-arg my_var=new_value -t image_name .

在构建过程中,Docker 将使用传递的值来覆盖 ARG 变量的默认值。

通过上述步骤,你可以在构建镜像时灵活地传递参数,从而定制化构建过程。这在需要根据不同环境或需求进行自定义构建的场景下非常有用。

CMD 结合 ENTRYPOINT

当使用 Docker 构建镜像时,可以使用 CMD 和 ENTRYPOINT 这两个指令来定义容器启动时要执行的命令或脚本。

  • ENTRYPOINT 指令用于设置容器启动时要执行的主要命令或脚本。
  • CMD 指令用于定义容器的默认执行命令,可以在运行容器时被覆盖。

它们可以结合使用,提供更灵活的容器启动方式。当二者同时存在时,CMD 的值会作为 ENTRYPOINT 的默认参数传递,并且 CMD 可以通过 docker run 的参数进行覆盖。

这样,我们可以在 Dockerfile 中设置容器启动时的默认命令,但也允许在运行容器时传入新的命令来替换默认值。这样的设计允许用户根据具体需求来调整容器的行为,增加了灵活性和自定义性。

COPY vs ADD

这俩都可以把宿主机的文件复制到容器内,

但有一点区别,就是对于 tar.gz 这种压缩文件的处理上。

ADD 把 tar.gz 给解压然后复制到容器内

而 COPY 没有解压,它把文件整个复制过去了

但是 ADD 还可以解压 tar.gz 文件。

一般情况下,还是用 COPY 居多

在 Docker 中,COPY 和 ADD 是两个用于将文件从主机复制到容器内部的指令。

COPY 指令的格式如下:

COPY <源路径> <目标路径>

它将主机上的文件或目录复制到容器中的目标路径。

ADD 指令与 COPY 类似,但功能更丰富:

ADD <源路径> <目标路径>

除了复制文件和目录外,ADD 还支持自动解压缩 tar 文件、从远程 URL 下载文件,并将它们复制到容器中的目标路径。

一般而言,在构建镜像时使用 COPY 指令更常见,因为它更简单且能满足基本的文件复制需求。只有在特定情况下需要自动解压缩或直接从远程下载文件时,才会考虑使用 ADD 指令。

docker Compose

Docker Compose 是一个用于定义和运行多个 Docker 容器的工具。它通过使用简单的 YAML 文件来配置和管理应用程序的服务、网络和卷等方面。Docker Compose 可以让你轻松地在单个主机上定义和管理多个容器,实现容器化应用程序的快速部署。

使用 Docker Compose,你可以将整个应用程序的多个服务组合在一起,并定义它们之间的关系和依赖。这样,你就可以使用一个命令来启动、停止和管理整个应用程序,而不是手动逐个管理每个容器。

以下是 Docker Compose 的主要特点和用法:

  1. 声明式语法:使用 YAML 文件编写 Docker Compose 配置,非常直观和易于理解。
  2. 多容器编排:定义和管理多个容器,包括镜像、端口映射、环境变量、数据卷等。
  3. 服务依赖:可以指定服务之间的依赖关系,确保它们按正确的顺序启动和关闭。
  4. 网络管理:可以定义自定义网络,使容器能够相互通信,并与外部网络隔离。
  5. 即时构建和重建:可以通过指定 Dockerfile 或镜像名称来构建和重建容器,保持代码和环境的同步。
  6. 扩展和伸缩性:可以根据需要通过指定副本数来扩展服务,实现负载均衡。
  7. 简化部署流程:使用一个命令(docker-compose up)即可启动整个应用程序,而不是手动操作每个容器。

总的来说,Docker Compose 是一个方便的工具,用于定义和管理 Docker 容器化应用程序的多个服务,简化了开发者在本地环境中的部署和管理过程。

常用命令

docker --version #查看版本docker-compose -h    # 查看帮助docker-compose up    # 启动所有docker-compose服务docker-compose up -d    # 启动所有docker-compose服务并后台运行docker-compose down     # 停止并删除容器、网络、卷、镜像。docker-compose exec  yml里面的服务id   # 进入容器实例内部  docker-compose exec docker-compose.yml文件中写的服务id /bin/bashdocker-compose ps      # 展示当前docker-compose编排过的运行的所有容器docker-compose top       # 展示当前docker-compose编排过的容器进程docker-compose logs  yml里面的服务id   # 查看容器输出日志docker-compose config     # 检查配置docker-compose config -q  # 检查配置,有问题才有输出docker-compose restart   # 重启服务docker-compose start     # 启动服务docker-compose stop      # 停止服务

services:nest-app:build:context: ./dockerfile: ./Dockerfiledepends_on: #会先启动另外两个,再启动这个- mysql-container- redis-containerports:- '3000:3000'mysql-container:image: mysqlports:- '3306:3306'volumes:- /Users/guang/mysql-data:/var/lib/mysqlredis-container:image: redisports:- '6379:6379'volumes:- /Users/guang/aaa:/data
docker-compose up

它会把所有容器的日志合并输出:

docker原理

docker的实现基于下面三方面:

  • Namespace:实现各种资源的隔离

类似这样的 namespace 一共有 6 种:

    • PID namespace: 进程 id 的命名空间
    • IPC namespace: 进程通信的命名空间
    • Mount namespace:文件系统挂载的命名空间
    • Network namespace:网络的命名空间
    • User namespace:用户和用户组的命名空间
    • UTS namespace:主机名和域名的命名空间

  • Control Group:实现容器进程的资源访问限制

但是只有命名空间的隔离还不够,还得对资源做限制。比如一个容器占用了太多的资源,那就会导致别的容器受影响。怎么能限制容器的资源访问呢?

这就需要 linux 操作系统的另一种机制:Control Group

创建一个 Control Group 可以给它指定参数,比如 cpu 用多少、内存用多少、磁盘用多少,然后加到这个组里的进程就会受到这个限制。

这样,创建容器的时候先创建一个 Control Group,指定资源的限制,然后把容器进程加到这个 Control Group 里,就不会有容器占用过多资源的问题了。


 

  • UnionFS:实现容器文件系统的分层存储,镜像合并

每个容器都是独立的文件系统,相互独立,而这些文件系统之间可能很大部分都是一样的,同样的内容占据了很大的磁盘空间,会导致浪费。

所以 Docker 设计了一种分层机制:每一层都是不可修改的,也叫做镜像

我本地两个 nest 镜像,它们都继承了 node 镜像,这两个合起来有 2g 的存储空间么?

没有,因为下面的镜像层是公用的:

使用案例

我的项目:

  • 个人网站 网站+后台管理系统+大屏+后端服务(node)
  • 掘金自动签到
  • 微信推送
version: '3'
services:mysql-blog:image: mysql:8.0container_name: mysql-blogrestart: unless-stoppedenvironment:- MYSQL_ROOT_PASSWORD=xxxxxvolumes:- /Users/liuzepeng/Desktop/all/docker/mysql-docker:/var/lib/mysqlnetworks:- common-networkports:- '3307:3306'auto-check-in:build:context: ./auto-check-indockerfile: Dockerfilecontainer_name: auto-check-in-containerrestart: unless-stoppedwechat_message:build:context: ./wechat_messagedockerfile: Dockerfilecontainer_name: wechat-message-containerrestart: unless-stoppedtodo-nodejs-api:build:context: ./todo-nodejs-apidockerfile: Dockerfilecontainer_name: todo-nodejs-api-containerrestart: unless-stoppeddepends_on:- mysql-blogports:- '8088:8088'networks:- common-networknetworks:common-network:driver: bridge

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/112525.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kubernetes(七)修改 pod 网络(flannel 插件)

一、 提示 需要重启服务器 操作之前备份 k8s 中所有资源的 yaml 文件 如下是备份脚本&#xff0c;仅供参考 # 创建备份目录 test -d $3 || mkdir $3 # $1 命名空间 # $2 资源名称&#xff1a; sts deploy configMap svc 等 # $3 资源备份存放的目录名称for app in kubec…

MySQL DATE_SUB的实践

函数简介DATE_SUB()函数从DATE或DATETIME值中减去时间值(或间隔)。 下面说明了DATE_SUB()函数的语法&#xff1a; DATE_SUB(start_date,INTERVAL expr unit); DATE_SUB()函数接受两个参数&#xff1a; start_date是DATE或DATETIME的起始值。 expr是一个字符串&#xff0c;用于确…

接口幂等性设计的最佳实现

一、什么是幂等 二、为什么需要幂等 三、接口超时了&#xff0c;到底如何处理&#xff1f; 四、如何设计幂等 全局的唯一性ID 幂等设计的基本流程 五、实现幂等的8种方案 selectinsert主键/唯一索引冲突 直接insert 主键/唯一索引冲突 状态机幂等 抽取防重表 token令牌 悲观锁…

【Jetpack】Navigation 导航组件 ⑤ ( NavigationUI 类使用 )

文章目录 一、NavigationUI 类简介二、NavigationUI 类使用流程1、创建 Fragment2、创建 NavigationGraph3、Activity 导入 NavHostFragment4、创建菜单5、Activity 界面开发 NavigationUI 的主要逻辑 ( 重点 )a、添加 Fragment 布局b、处理 Navigation 导航逻辑 ( 重点 )c、启…

MacOS goland go1.21 debug问题

安装dlv brew install dlv 安装之后在终端会显示所在目录 类似/usr/local/Cellar/delve/1.21.0/bin 配置goland 在文件系统中找到goland 右击选择show package contents -> Contents -> plugins -> go 尝试替换 其中对应系统 的 dlv 结果还是不行 然后打开应用gol…

Huggingface托管机器学习模型及API提供

推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 我想在我的网络和移动应用程序中使用机器学习模型&#xff0c;但要做到这一点&#xff0c;我必须在某个地方托管我的机器学习应用程序。 托管预先训练的 ML 模型称为推理。 我只想添加一些 Python ML 代码并快速获得 REST…

【拾枝杂谈】从游戏开发的角度来谈谈原神4.0更新

君兮_的个人主页 勤时当勉励 岁月不待人 C/C 游戏开发 Hello,米娜桑们&#xff0c;这里是君兮_&#xff0c;结合最近的学习内容和以后自己的目标&#xff0c;今天又开了杂谈这个新坑&#xff0c;分享一下我在学习游戏开发的成长和自己的游戏理解&#xff0c;当然现在还是一枚…

尚硅谷大数据项目《在线教育之离线数仓》笔记003

视频地址&#xff1a;尚硅谷大数据项目《在线教育之离线数仓》_哔哩哔哩_bilibili 目录 第8章 数仓开发之DIM层 P039 P040 P041 P042 P043 P044 P045 P046 P047 P048 第8章 数仓开发之DIM层 P039 第8章 数仓开发之DIM层 DIM层设计要点&#xff1a; &#xff08;1&a…

Docker容器学习:搭建自己专属的LAMP环境

目录 编写Dockerfile 1.文件内容需求&#xff1a; 2.值得注意的是centos6官方源已下线&#xff0c;所以需要切换centos-vault源&#xff01; 3.Dockerfile内容 4.进入到 lamp 开始构建镜像 推送镜像到私有仓库 1.把要上传的镜像打上合适的标签 2.登录harbor仓库 3.上传镜…

jsp+servlet+mysql阳光网吧管理系统

项目介绍&#xff1a; 本系统使用jspservletmysql开发的阳光网吧管理系统&#xff0c;纯手工敲打&#xff0c;系统管理员和用户角色&#xff0c;功能如下&#xff1a; 管理员&#xff1a;修改个人信息、修改密码&#xff1b;机房类型管理&#xff1b;机房管理&#xff1b;机位…

大数据之linux入门

一、linux是什么 linux操作系统 开发者是林纳斯-托瓦兹&#xff0c;出于个人爱好编写。linux是一个基于posix和unix的多用户、多任务、支持多线程和多CPU的操作系统。 Unix是20世纪70年代初出现的一个操作系统&#xff0c;除了作为网络操作系统之外&#xff0c;还可以作为单…

Redis五种类型

Redis 基础类型 String 应用场景 缓存功能&#xff1a;string 最常用的就是缓存功能&#xff0c;会将一些更新不频繁但是查询频繁的数据缓存起来&#xff0c;以此来减轻 DB 的压力。 底层实现 如果字符串对象保存的是一个字符串值&#xff0c; 并且这个字符串值的长度大于…

【SpringCloudAlibaba】Nacos服务注册和配置中心配合nginx负载

文章目录 概述注册中心POMYML启动类 CAP配置中心POMYML启动类ConfigClientControllerNacos中的匹配规则三种方案加载配置示例 集群部署概述部署模式修改derby为mysql配置cluster.conf编辑Nacos的启动脚本startup.sh&#xff0c;使它能够接受不同的启动端口Nginx的配置&#xff…

Android 13 - Media框架(8)- MediaExtractor

上一篇我们了解了 GenericSource 需要依赖 IMediaExtractor 完成 demux 工作&#xff0c;这一篇我们就来学习 android media 框架中的第二个服务 media.extractor&#xff0c;看看 IMediaExtractor 是如何创建与工作的。 1、MediaExtractorService media.extractor 和 media.p…

资源分享| 4种聚类算法及可视化(Python)

在这篇文章中&#xff0c;基于20家公司的股票价格时间序列数据。根据股票价格之间的相关性&#xff0c;看一下对这些公司进行聚类的四种不同方式。 苹果&#xff08;AAPL&#xff09;&#xff0c;亚马逊&#xff08;AMZN&#xff09;&#xff0c;Facebook&#xff08;META&…

Unity打包Windows程序,概率性出现无法全屏或分辨率不匹配

排除代码和Resolution and Presentation面板设置问题 如果程序还是不能按照预期的分辨率运行&#xff0c;应该是系统注册表记录了对应的设置。 解决方案&#xff1a; 打开注册表&#xff0c;使用快捷键“Win” "R"组合快捷键。在打开后面键入命令&#xff1a;Rege…

AR地图微信小程序:数字化时代下地图应用的新突破

随着数字化时代的到来&#xff0c;地图应用成为人们日常生活中不可或缺的工具。而随着增强现实&#xff08;AR&#xff09;技术的快速发展&#xff0c;AR地图微信小程序应运而生&#xff0c;为用户提供了一种全新的地图导航体验。本文将深入探讨AR地图微信小程序的专业性和思考…

【网络】多路转接——poll | epoll

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《网络》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 书接上文五种IO模型 | select。 poll | epoll &#x1f367;poll&#x1f9c1;认识接口&#x1f9c1;简…

java解析html

目录 场景描述一.引入依赖二.调用接口响应回来的html三.测试代码 场景描述 我调用外部接口&#xff0c;但是返回来的数据是html的格式&#xff0c;所以我就需要进行处理来获得我想要的数据。我使用的是jsoup。 一.引入依赖 <dependency><groupId>org.jsoup</gr…

js reverse实现数据的倒序

2023.8.25今天我学习了如何在数组顺序进行倒序排列&#xff0c;如&#xff1a; 原数组为&#xff1a; 我们只需要对数组使用reverse()方法 let demo [{id: 1, name: 一号},{id: 2, name: 二号},{id: 3, name: 三号},]demo.reverse()console.log(demo) 扩展&#xff1a; 当我…