Linux——Dockerfile

news2024/11/16 23:41:35

在这里我们来整理一下docker容器、dockerfile、docker镜像的关系:

dockerfile是面向开发的,发布项目做镜像的时候就要编写dockerfile文件。
dockerfile:构建文件,定义了一切的步骤,源代码。
dockerImanges:通过dockerfile构建生成的镜像,最终发布和运行的产品。
docker容器:容器就是镜像运行起来提供服务的

一、Dockerfile 指令选项。

Dockerfile 指令选项:

FROM                  #基础镜像 。 (centos)
MAINTAINER            #镜像的作者和邮箱。(已被弃用,结尾介绍代替词)
RUN                   #镜像构建的时候需要执行的命令。
CMD                   #类似于 RUN 指令,用于运行程序(只有最后一个会生效,可被替代)
EXPOSE                #对外开放的端口。
ENV                   #设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
ADD                   # 步骤:tomcat镜像,这个tomcat压缩包。添加内容。
COPY                  #复制指令,将文件拷贝到镜像中。
VOLUME                #设置卷,挂载的主机目录。
USER                  #用于指定执行后续命令的用户和用户组,
                       这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。
WORKDIR               #工作目录(类似CD命令)。
ENTRYPOINT            #类似于 CMD 指令,但其不会被 docker run 
                       的命令行参数指定的指令所覆盖,会追加命令。
ONBUILD               #当构建一个被继承Dokcerfile,就会运行ONBUILD的指令。出发执行。


注意:CMD类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:
CMD 在docker run 时运行。
RUN 是在 docker build。
作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。
CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

LABEL(MAINTALNER已经被弃用了,目前是使用LABEL代替)
LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
比如我们可以添加镜像的作者:
LABEL org.opencontainers.image.authors="runoob"

ENV 设置环境变量:

格式有两种:

    ENV <key> <value>

ENV <key1>=<value1> <key2>=<value2>...

这个指令很简单,就是设置环境变量而已,无论是后面的其它指令,如 RUN,还是运行时的应用,都可以直接使用这里定义的环境变量。

ARG 构建参数:

格式:ARG <参数名>[=<默认值>]

构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是,ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。但是不要因此就使用 ARG 保存密码之类的信息,因为 docker history 还是可以看到所有值的。

EXPOSE 声明端口:

格式为 EXPOSE <端口1> [<端口2>...]。

EXPOSE 指令是声明容器运行时提供服务的端口,这只是一个声明,在容器运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。-p,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。

WORKDIR 指定工作目录:

格式为 WORKDIR <工作目录路径>。

使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录

[root@docker1 ~]# mkdir /test-multi
[root@docker1 ~]# cd /test-multi
[root@docker1 test-multi]# vim Dockerfile
[root@docker1 test-multi]# cat Dockerfile
FROM centos
ENV aa=1  bb=2  cc=3 envdir=/a/b/c
ARG dd=4  ee=5  ff=6 argdir=/a/b/c
WORKDIR $argdir
COPY test.sh $envdir
RUN echo $aa $bb $cc $dd $dd $ff > /var.txt
CMD ["./test.sh"]
[root@docker1 test-multi]#
[root@docker1 test-multi]# vim test.sh
[root@docker1 test-multi]# cat test.sh
#! /bin/bash
echo output env vars:
echo $aa $bb $cc
echo output arg vars:
echo $dd $ee $ff
echo current work directory:
pwd
[root@docker1 test-multi]#
[root@docker1 test-multi]# chmod +x test.sh



[root@docker1 test-multi]# docker build -t mymulti:v1 .
……
=> [2/4] WORKDIR /a/b/c                                                              0.1s
 => [3/4] COPY test.sh /a/b/c                                                         0.0s
 => [4/4] RUN echo 1 2 3 4 4 6 > /var.txt   
……

验证:
[root@docker1 test-multi]# docker run --rm mymulti:v1
output env vars:
1 2 3
output arg vars:

current work directory:
/a/b/c
[root@docker1 test-multi]#

VOLUME 定义匿名卷:

格式为:

    VOLUME ["<路径1>", "<路径2>"...]

    VOLUME <路径>

之前我们说过,容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中,后面的章节我们会进一步介绍 Docker 卷的概念。为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。

[root@docker1 ~]# mkdir /test_volume
[root@docker1 ~]# cd /test_volume
[root@docker1 test_volume]#
[root@docker1 test_volume]# cat Dockerfile
from alpine
RUN mkdir /test && touch /test/test.txt
[root@docker1 test_volume]# docker build -t myvolume:v1 .
[root@docker1 test_volume]# docker run -it myvolume:v1 sh
/ # cat /test/test.txt 
/ # echo 123 > /test/test.txt 
/ # cat /test/test.txt 
123
/ # exit
[root@docker1 test_volume]# docker ps -a
CONTAINER ID   IMAGE         COMMAND   CREATED          STATUS                     PORTS     NAMES
c2de419ef2d3   myvolume:v1   "sh"      36 seconds ago   Exited (0) 3 seconds ago             zealous_lumiere
[root@docker1 test_volume]#
[root@docker1 test_volume]# docker start zealous_lumiere 
zealous_lumiere
[root@docker1 test_volume]# docker ps -a
CONTAINER ID   IMAGE         COMMAND   CREATED              STATUS         PORTS     NAMES
c2de419ef2d3   myvolume:v1   "sh"      About a minute ago   Up 7 seconds             zealous_lumiere
[root@docker1 test_volume]# docker exec -it zealous_lumiere sh
/ # cat /test/test.txt 
123
/ # exit
[root@docker1 test_volume]# docker stop zealous_lumiere 
zealous_lumiere
[root@docker1 test_volume]# docker rm zealous_lumiere 
zealous_lumiere
[root@docker1 test_volume]#注:容器没删除,则数据存在

重新创建的容器没有之前的数据,数据是非持久化的:
[root@docker1 test_volume]# docker run -it --name mv1  myvolume:v1 sh
/ # cat /test/test.txt 
/ # exit
[root@docker1 test_volume]# docker rm mv1 
mv1
[root@docker1 test_volume]#

匿名卷:

[root@docker1 test_volume]# cat Dockerfile

from alpine

RUN mkdir /test && touch /test/test.txt

VOLUME /test

[root@docker1 test_volume]#

[root@docker1 test_volume]# docker build -t myvolume:v2 .

[root@docker1 test_volume]# docker run --rm -d myvolume:v2 sleep 100

2b2922070b503298b4195c7fa7007a6b0f3f51528f035098beb4d32801288c11

[root@docker1 test_volume]#

[root@docker1 test_volume]# docker run --rm -d myvolume:v2 sleep 100

2b2922070b503298b4195c7fa7007a6b0f3f51528f035098beb4d32801288c11

[root@docker1 test_volume]# docker ps -a

CONTAINER ID   IMAGE         COMMAND       CREATED          STATUS          PORTS     NAMES

2b2922070b50   myvolume:v2   "sleep 100"   13 seconds ago   Up 13 seconds             eloquent_agnesi

[root@docker1 test_volume]# docker inspect eloquent_agnesi | grep -i -A 5 mounts

        "Mounts": [

            {

                "Type": "volume",

                "Name": "581af512e8399049c748fb8f2918df6041435aba355b83618537accbada60f72",

                "Source": "/var/lib/docker/volumes/581af512e8399049c748fb8f2918df6041435aba355b83618537accbada60f72/_data",

                "Destination": "/test",

[root@docker1 test_volume]# docker volume ls

DRIVER    VOLUME NAME

local     581af512e8399049c748fb8f2918df6041435aba355b83618537accbada60f72

[root@docker1 test_volume]#

[root@docker1 test_volume]# docker ps -a(容器停止后自动删除了)

CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

[root@docker1 test_volume]# docker volume ls 匿名卷生命周期跟随容器

DRIVER    VOLUME NAME

[root@docker1 test_volume]#

不在dockerfile定义volume也可以启用匿名卷:

[root@docker1 test_volume]# docker run -d -v /opt alpine sleep 200

37d9216c975dac39d75845bfa14db0b983d8eb710d1072ce75d16b5d609d54db

[root@docker1 test_volume]# docker volume ls

DRIVER    VOLUME NAME

local     847f7e6cc35beca7f50a9a6b41c28a84b7d60abfabd3e7677636f84f5d8694a4

[root@docker1 test_volume]#

[root@docker1 test_volume]# docker rmi myvolume:v2

Untagged: myvolume:v2

Deleted: sha256:6ccc8e360eed876906d7bf5fdd8109a995e7afe11b8595f00ec594db81760664

[root@docker1 test_volume]#

持久存储:推荐使用命名卷或者宿主机目录(或共享的目录)

数据卷管理:数据持久化

这一章介绍如何在 Docker 内部以及容器之间管理数据,在容器中管理数据主要有两种方式:

    数据卷(Volumes)

挂载主机目录 (Bind mounts)

[root@docker1 test_volume]# docker volume ls
DRIVER    VOLUME NAME
[root@docker1 test_volume]#
[root@docker1 test_volume]# docker volume create my-vol1
my-vol1
[root@docker1 test_volume]# docker volume ls
DRIVER    VOLUME NAME
local     my-vol1
[root@docker1 test_volume]#
[root@docker1 test_volume]# docker inspect my-vol1 
[
    {
        "CreatedAt": "2024-05-21T09:32:49+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/my-vol1/_data",
        "Name": "my-vol1",
        "Options": null,
        "Scope": "local"
    }
]
[root@docker1 test_volume]#

[root@docker1 test_volume]# cat Dockerfile 
from alpine
RUN mkdir /test && touch /test/test.txt
VOLUME /test
[root@docker1 test_volume]#
[root@docker1 test_volume]# docker build -t myvolume:v2 .
[root@docker1 test_volume]# docker inspect myvolume:v2| grep -i -A 2  volumes
            "Volumes": {
                "/test": {}
            },
[root@docker1 test_volume]#

[root@docker1 test_volume]# docker run -it --rm  -v my-vol1:/test myvolume:v2 sh
/ # cat /test/test.txt 
/ # echo 123 > /test/test.txt 
/ # echo 456 > /test/test2.txt
/ # exit
[root@docker1 test_volume]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@docker1 test_volume]# docker run -it --rm  -v my-vol1:/test myvolume:v2 sh
/ # cat /test/test.txt 
123
/ # cat /test/test2.txt 
456
/ # exit
[root@docker1 test_volume]#
[root@docker1 ~]# ls /var/lib/docker/volumes/my-vol1/_data
test2.txt  test.txt
[root@docker1 ~]#

[root@docker1 test_volume]# docker run -it --rm  --mount source=my-vol1,target=/test myvolume:v2 sh
/ # cat /test/test2.txt 
456
/ # exit
[root@docker1 test_volume]#

Linux目录挂载:加bind选项
[root@docker1 ~]# mkdir /a /b
[root@docker1 ~]# touch  /b/b.txt
[root@docker1 ~]# mount /a /b
mount: /b: /a is not a block device.
[root@docker1 ~]# mount -o bind /a /b
[root@docker1 ~]# ls /b
[root@docker1 ~]# umount /b
[root@docker1 ~]# ls /b
b.txt
[root@docker1 ~]#

[root@docker1 test_volume]# mkdir /testmount
[root@docker1 test_volume]# echo 3 > /testmount/3.txt
[root@docker1 test_volume]# docker run -it --rm  --mount type=bind,source=/testmount,target=/test myvolume:v2 sh
/ # ls /test
3.txt
/ # echo 33 > /test/3.txt 
/ # exit
[root@docker1 test_volume]# docker run -it --rm  --mount type=bind,source=/testmount,target=/test,readonly myvolume:v2 sh
/ # cat /test/3.txt 
33
/ # echo 333 > /test/3.txt 
sh: can't create /test/3.txt: Read-only file system
/ # exit
[root@docker1 test_volume]#

容器共享存储:

[root@docker1 ~]# ls /webdir/
Dockerfile  page1.html  page2.html
[root@docker1 ~]# cat /webdir/page1.html 
page1
[root@docker1 ~]# cat /webdir/page2.html 
page2
[root@docker1 ~]#
[root@docker1 test_volume]# docker run -d --rm --name nginx1 -v /webdir:/usr/share/nginx/html -p 81:80 nginx:latest 
6b9920b4b7d3f666c486a1d372b45fa01b63cd64252fbdc629053aff0b953ce8
[root@docker1 test_volume]# docker run -d --rm --name nginx2 -v /webdir:/usr/share/nginx/html -p 82:80 nginx:latest 
9666d000921ee7d78edaf8fc0f91ab4127b68ca9195c70601fa3eaf628c79616
[root@docker1 test_volume]# curl 127.0.0.1:81/page1.html
page1
[root@docker1 test_volume]# curl 127.0.0.1:82/page1.html
page1
[root@docker1 test_volume]# docker stop nginx1
nginx1
[root@docker1 test_volume]# docker stop nginx2
nginx2
[root@docker1 test_volume]#

使用local以外的volume driver:

使用vieux/sshfs:

安装插件:

[root@docker1 test_volume]# docker plugin install --grant-all-permissions vieux/sshfs
latest: Pulling from vieux/sshfs
Digest: sha256:1d3c3e42c12138da5ef7873b97f7f32cf99fb6edde75fa4f0bcf9ed277855811
52d435ada6a4: Complete 
Installed plugin vieux/sshfs
[root@docker1 test_volume]#

[root@docker2 ~]# mkdir /sharedir
[root@docker2 ~]# touch /sharedir/share.txt

创建卷:

[root@docker1 test_volume]# docker volume create --driver vieux/sshfs -o sshcmd=root@192.168.99.129:/sharedir -o password=1 sshvolume
sshvolume
[root@docker1 test_volume]#
[root@docker1 test_volume]# docker volume ls
DRIVER               VOLUME NAME
local                my-vol1
vieux/sshfs:latest   sshvolume
[root@docker1 test_volume]#
[root@docker1 test_volume]# docker run -it --rm -v sshvolume:/opt alpine sh
/ # ls /opt/
share.txt
/ # exit
[root@docker1 test_volume]#
(
官方参考如下:
docker run -d \
  --name sshfs-container \
  --volume-driver vieux/sshfs \
  --mount src=sshvolume,target=/app,volume-opt=sshcmd=test@node2:/home/test,volume-opt=password=testpassword \
  nginx:latest
)
使用基于nfs的卷:
(
官方参考如下:
Nfsv3:
docker service create -d \
  --name nfs-service \
  --mount 'type=volume,source=nfsvolume,target=/app,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/var/docker-nfs,volume-opt=o=addr=10.0.0.10' \
  nginx:latest

nfsv4:
docker service create -d \
    --name nfs-service \
    --mount 'type=volume,source=nfsvolume,target=/app,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/var/docker-nfs,"volume-opt=o=addr=10.0.0.10,rw,nfsvers=4,async"' \
    nginx:latest
)
配置nfs服务,自行解决防火墙和selinux:
[root@docker2 ~]# mkdir /nfs1 /nfs2
[root@docker2 ~]# chmod 777  /nfs1 /nfs2
[root@docker2 ~]# vim /etc/exports
[root@docker2 ~]# cat /etc/exports
/nfs1  *(rw,no_root_squash)
/nfs2 *(rw,no_root_squash)
[root@docker2 ~]# 
[root@docker2 ~]# systemctl start nfs-server.service

[root@docker1 test_volume]# yum -y install nfs-utils
[root@docker1 test_volume]# showmount -e 192.168.99.129
Export list for 192.168.99.129:
/nfs2 *
/nfs1 *
[root@docker1 test_volume]#

手动创建卷:

[root@docker1 test_volume]# docker volume create --driver local -o type=nfs -o device=:/nfs1 -o o=addr=192.168.99.129,rw,nfsvers=4  nfs1volume
nfs1volume
[root@docker1 test_volume]#
[root@docker1 test_volume]# docker volume ls
DRIVER               VOLUME NAME
local                my-vol1
local                nfs1volume
vieux/sshfs:latest   sshvolume
[root@docker1 test_volume]#
验证:
[root@docker1 test_volume]# docker run -it --rm --mount 'type=volume,source=nfs1volume,target=/opt,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/nfs1,"volume-opt=o=addr=192.168.99.129,rw,nfsvers=4"' --privileged alpine sh
/ # touch /opt/1.txt
/ # exit
[root@docker1 test_volume]#
[root@docker2 ~]# ls /nfs1
1.txt
[root@docker2 ~]#
[root@docker1 test_volume]# docker run -it --rm --mount 'type=volume,source=nfs1volume,target=/opt' --privileged alpine sh
/ # ls /opt/
1.txt
/ # exit
[root@docker1 test_volume]#

创建容器时自动创建nfs卷:

[root@docker1 ~]# docker volume ls
DRIVER               VOLUME NAME
local                my-vol1
local                nfs1volume
vieux/sshfs:latest   sshvolume
[root@docker1 ~]#
[root@docker1 test_volume]# docker run -it --rm --mount 'type=volume,source=nfs2volume,target=/opt,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/nfs2,"volume-opt=o=addr=192.168.99.129,rw,nfsvers=4"' --privileged alpine sh
/ # touch /opt/2.txt
/ # exit
[root@docker1 test_volume]# 
[root@docker1 test_volume]# docker volume ls
DRIVER               VOLUME NAME
local                my-vol1
local                nfs1volume
local                nfs2volume
vieux/sshfs:latest   sshvolume
[root@docker1 test_volume]#
[root@docker2 ~]# ls /nfs2
2.txt
[root@docker2 ~]#

练习:使用samba共享提供持久存储

官方参考:

docker volume create \

--driver local \

--opt type=cifs \

--opt device=//uxxxxx.your-server.de/backup \

--opt o=addr=uxxxxx.your-server.de,username=uxxxxxxx,password=*****,file_mode=0777,dir_mode=0777 \

--name cif-volume

其他数据卷内容参考:Volumes | Docker DocsLearn how to create, manage, and use volumes instead of bind mounts for persisting data generated and used by Docker.icon-default.png?t=N7T8https://docs.docker.com/storage/volumes/

USER 指定当前用户:

格式:USER <用户名>[:<用户组>]

USER 指令和 WORKDIR 相似,都是改变环境状态并影响以后的层。WORKDIR 是改变工作目录,USER 则是改变之后层的执行 RUN, CMD 以及 ENTRYPOINT 这类命令的身份。

USER 只是帮助你切换到指定用户而已,这个用户必须是事先建立好的,否则无法切换。

[root@docker1 test_volume]# vim Dockerfile 
[root@docker1 test_volume]# cat Dockerfile
from centos
RUN id > /user.txt && chmod 777 /user.txt
RUN useradd test 
USER test
RUN  id >> /user.txt
CMD cat /user.txt
[root@docker1 test_volume]#
[root@docker1 test_volume]# docker build -t test-user:v1 .
[root@docker1 test_volume]# docker run -it --rm test-user:v1 
uid=0(root) gid=0(root) groups=0(root)
uid=1000(test) gid=1000(test) groups=1000(test)
[root@docker1 test_volume]#

HEALTHCHECK 健康检查:

格式:

 HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令

 HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

HEALTHCHECK 指令是告诉 Docker 应该如何进行判断容器的状态是否正常,这是 Docker 1.12 引入的新指令。

[root@docker1 ~]# mkdir /test-health
[root@docker1 ~]# cd /test-health
[root@docker1 test-health]# vim Dockerfile
[root@docker1 test-health]# cat Dockerfile
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s  CMD curl -fs http://localhost/ || exit 1
[root@docker1 test-health]# docker build -t myhealth:v1 .

另起一个终端,每秒刷新一次docker ps -a的输出:
[root@docker1 ~]# watch -n 1 docker ps -a

[root@docker1 test-health]# docker run -d --rm --name myh myhealth:v1 
a1fffb3d0193408d81a1db9484576a3e2df214b12d9fa19ae78da6ff875d7704
[root@docker1 test-health]#
[root@docker1 ~]# docker ps -a
CONTAINER ID   IMAGE         COMMAND                  CREATED          STATUS                    PORTS     NAMES
a1fffb3d0193   myhealth:v1   "/docker-entrypoint.…"   28 seconds ago   Up 27 seconds (healthy)   80/tcp    myh
[root@docker1 ~]# 速度快,可以看到从starting到healthy的过程

为了帮助排障,健康检查命令的输出(包括 stdout 以及 stderr)都会被存储于健康状态里,可以用 docker inspect 来查看。
[root@docker1 test-health]#  docker inspect --format '{{json .State.Health}}' myh | python3 -m json.tool

模拟故障:

再容器中删除index.html,因为健康检查指令curl -fs http://localhost/ || exit 1查看的时首页,此时删除首页则访问报错,但是不能使用nginx -s stop停服务,因为nginx进程是容器的主体进程,停服务则容器退出:

[root@docker1 test-health]# docker exec -it myh sh
# ls /usr/share/nginx/html/index.html
/usr/share/nginx/html/index.html
# rm -rf /usr/share/nginx/html/index.html
# exit
[root@docker1 test-health]#
等待一段时间可以看到unhealthy:
[root@docker1 ~]# docker ps -a
CONTAINER ID   IMAGE         COMMAND                  CREATED         STATUS                     PORTS     NAMES
cf26f8e926d2   myhealth:v1   "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes (unhealthy)   80/tcp    myh
[root@docker1 ~]#
自行创建index.html,测试恢复为healthy的过程

[root@docker1 test-health]# vim Dockerfile 
[root@docker1 test-health]# cat Dockerfile
FROM alpine
LABEL custom alpine

[root@docker1 test-health]# docker build -t mylabel:v1 .
[root@docker1 test-health]# docker image ls -f LABEL=custom
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
mylabel      v1        bcefe279deed   3 months ago   7.38MB
[root@docker1 test-health]#

SHELL 指令:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【AI绘画Stable Diffusion】单人LoRA模型训练,打造你的专属模型,新手入门宝典请收藏!

大家好&#xff0c;我是灵魂画师向阳 本期我将教大家如何进行LoRA模型训练&#xff0c;打造你的专属模型&#xff0c;内容比较干&#xff0c;还请耐心看完&#xff01; 随着AIGC的发展&#xff0c;许多传统工作岗位正逐渐被AI取代。同时&#xff0c;AI变革也在创造前所未有的…

STM32 学习——1. STM32最小系统

这是一个最小系统的测试&#xff0c;LED灯会进行闪烁。选用PC13口&#xff0c;因为STM32F103C8T6 硬件开发板中&#xff0c;这个端口是一个LED 1. proteus8.15 原理图 2. cubemx 新建工程 3. keil 代码 while (1){HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);HAL_Delay(100);…

《计算机网络微课堂》1-3 三种交换方式

本节课我们介绍三种交换方式&#xff0c;分别是电路交换&#xff08;Circuit Switching&#xff09;&#xff0c;分组交换&#xff08;Packet Switching&#xff09;以及报文&#xff08;Message Switching&#xff09;交换。 我们首先来看电路交换&#xff0c;在电话问世后不…

探索未来,与移动云共舞

探索未来&#xff0c;与移动云共舞 在数字化飞速发展的今天&#xff0c;云计算已经成为企业、政府乃至个人用户不可或缺的一部分。而在众多云服务提供商中&#xff0c;移动云凭借其独特的优势&#xff0c;为用户带来前所未有的体验。接下来&#xff0c;让我们一起走进移动云的世…

Python--List列表

list列表⭐⭐ 1高级数据类型 Python中的数据类型可以分为&#xff1a;数字型&#xff08;基本数据类型&#xff09;和非数字型&#xff08;高级数据类型&#xff09; ●数字型包含&#xff1a;整型int、浮点型float、布尔型bool、复数型complex ●非数字型包含&#xff1a;字符…

Python实现数据可视化效果图总结

一、JSON格式 JSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去组织和封装数据。 JSON本质上是一个带有特定格式的字符串 Json格式 JSON数据格式在Python中可以是字典、又可以是列表中嵌套着字典的格式。 Pyhton数据和Json数据相互转化 二、pyecharts模块 如果想…

SpringMVC接收请求参数的方式:

接收简单变量的请求参数 直接使用简单变量作为形参进行接收&#xff08;这里简单变量名称需要与接收的参数名称保持一致&#xff0c;否则需要加上RequestParam注解&#xff09;&#xff1a; 细节&#xff1a; 1&#xff1a;SpringMVC会针对常见类型&#xff08;八种基本类型及…

翻译《The Old New Thing》- The importance of the FORMAT_MESSAGE_IGNORE_INSERTS flag

The importance of the FORMAT_MESSAGE_IGNORE_INSERTS flag - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20071128-00/?p24353 Raymond Chen 2007年11月28日 FORMAT_MESSAGE_IGNORE_INSERTS 标志的重要性 简要 文章讨论了使用FormatMes…

数据结构----堆的实现(附代码)

当大家看了鄙人的上一篇博客栈后&#xff0c;稍微猜一下应该知道鄙人下一篇想写的博客就是堆了吧。毕竟堆栈在C语言中常常是一起出现的。那么堆是什么&#xff0c;是如何实现的嘞。接下来我就带大家去尝试实现一下堆。 堆的含义 首先我们要写出一个堆&#xff0c;那么我们就需…

nodejs 与 npm 版本对应关系

官方地址&#xff1a;https://nodejs.org/en/about/previous-releases

手机边听边充音频转接器双盲插系列:便捷充电,畅享音乐6500

在快节奏的生活中&#xff0c;手机已经成为我们不可或缺的日常用品。无论是工作、学习还是娱乐&#xff0c;手机都扮演着重要角色。然而&#xff0c;当我们沉浸在音乐的海洋中时&#xff0c;手机电量不足的困扰却时常打断我们的美好体验。为了解决这一难题&#xff0c;手机边听…

你真正了解 Java 中的 Date 类吗?以及如何正确使用它

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

设计模式8——原型模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 原型模式&#xff08;Prototyp…

css卡片横线100%宽度

所需样式: 横线不用border, 用单独一个div, 这样就不会影响父组件的padding <div class"pumpDetailView"><div class"pump_title_name"><span>{{ pumpInfo.pointname }}</span><divclass"point_state":style"…

vr商品全景展示场景编辑软件的优点

3D模型展示网站搭建编辑器以强大的3D编辑引擎和逼真的渲染效果&#xff0c;让您轻松实现模型展示的优化。让用户通过简单的操作&#xff0c;就能满足个人/设计师/商户多样化展示的需求&#xff0c;让您的模型成为独一无二的杰作。 3D模型展示网站搭建编辑器采用国内领先的实时互…

玩转盲盒潮流:从0到1搭建小程序平台

在当前的消费市场中&#xff0c;盲盒已成为一种炙手可热的消费模式&#xff0c;凭借其神秘性和随机性&#xff0c;迅速俘获了年轻消费者的心。作为一位有志于创新并紧跟市场趋势的创业者&#xff0c;你可能会想&#xff1a;如何从0到1搭建一个属于自己的盲盒小程序平台&#xf…

kafka跨地区跨集群同步工具MirrorMaker2 —— 筑梦之路

MM2简介 KIP-382: MirrorMaker 2.0 - Apache Kafka - Apache Software Foundation 有四种运行MM2的方法&#xff1a; As a dedicated MirrorMaker cluster.&#xff08;作为专用的MirrorMaker群集&#xff09; As a Connector in a distributed Connect cluster.&#xff08…

基本IO接口

引入 基本输入接口 示例1 示例2&#xff1a;有数据保持能力的外设 #RD端由in指令控制&#xff1a;将数据由端口传输到CPU内存中 #CS244信号由译码电路实现 示例3&#xff1a; a)图中由于输出端口6有连接到端口1&#xff0c;当开关与端点1闭合时期间&#xff0c;仍能维持3端口…

开放式耳机2024超值推荐!教你如何选择蓝牙耳机!

开放式耳机的便利性让它在我们的日常生活中变得越来越重要。它让我们摆脱了传统耳机的限制&#xff0c;享受到了更多的自由。不过&#xff0c;市面上的开放式耳机种类繁多&#xff0c;挑选一款既实用又实惠的产品确实需要一些小窍门。作为一位对开放式耳机颇有研究的用户&#…

柯桥职场人出差必备的商务口语-职场差旅口语提问篇

May I reconfirm my flight? 我可以确认我的班机15857575376吗&#xff1f; Where can I make a reservation? 我到哪里可以预订&#xff1f; Do I have to make a reconfirmation? 我还要再确认吗&#xff1f; Is there any discount for the USA Railpass? 火车通行…