Linux——Dockerfile

在这里我们来整理一下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.https://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 指令:

相关推荐
韩楚风8 分钟前
【linux 多进程并发】linux进程状态与生命周期各阶段转换,进程状态查看分析,助力高性能优化
linux·服务器·性能优化·架构·gnu
陈苏同学11 分钟前
4. 将pycharm本地项目同步到(Linux)服务器上——深度学习·科研实践·从0到1
linux·服务器·ide·人工智能·python·深度学习·pycharm
Ambition_LAO17 分钟前
解决:进入 WSL(Windows Subsystem for Linux)以及将 PyCharm 2024 连接到 WSL
linux·pycharm
Pythonliu734 分钟前
茴香豆 + Qwen-7B-Chat-Int8
linux·运维·服务器
你疯了抱抱我35 分钟前
【RockyLinux 9.4】安装 NVIDIA 驱动,改变分辨率,避坑版本。(CentOS 系列也能用)
linux·运维·centos
追风赶月、35 分钟前
【Linux】进程地址空间(初步了解)
linux
栎栎学编程36 分钟前
Linux中环境变量
linux
我是哈哈hh1 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
郭二哈1 小时前
C++——模板进阶、继承
java·服务器·c++
挥剑决浮云 -1 小时前
Linux 之 安装软件、GCC编译器、Linux 操作系统基础
linux·服务器·c语言·c++·经验分享·笔记