当前位置: 首页 > news >正文

企业化运维(8)Docker容器技术

###1.Docker介绍###

什么是Docker

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

Docker为应用打包、部署平台,而非单纯的虚拟化技术。

一个完整的 Docker 由以下几个部分组成:

DockerClient 客户端

Docker Daemon 守护进程

Docker Image 镜像

DockerContainer 容器

VM VS Container

传统虚拟化与容器技术对比

docker容器的优势

更高效的利用系统资源
更快速的启动时间
一致的运行环境
持续支付和部署
更轻松的迁移
更轻松的维护和拓展

• 对于开发人员:Build once、Run anywhere。

• 对于运维人员:Configure once、Run anything。

容器技术大大提升了IT人员的幸福指数! 

容器工作原理

Docker 使用客户端 - 服务器(C/S)架构,使用远程API管理和创建Docker 容器。Docker 客户端与 Docker 守护进程通信,后者负责构建,运行和分发 Docker容器。Docker客户端和守护进程可以在同一系统上运行,也可以将Docker客户端连接到远程Docker守护进程。Docker客户端和守护进程使用REST API,通过UNIX套接字或网络接口进行通信。

Client:客户端通过命令行或其他工具与守护进程通信,客户端会将这些命令发送给守护进程,然后执行这些命令。命令使用Docker API,Docker客户端可以与多个守护进程通信。

Docker daemon:Docker守护进程(docker daemon)监听Docker API请求并管理Docker对象,如镜像,容器,网络和卷。守护程序还可以与其他守护程序通信以管理Docker服务。

Docker Host:Docker Host 是物理机或虚拟机,用于执行Docker守护进程的仓库。

Docker Registry:Docker仓库用于存储Docker镜像,可以是Docker Hub这种公共仓库,也可以是个人搭建的私有仓库。使用docker pull或docker run命令时,将从配置的仓库中提取所需的镜像。使用docker push命令时,镜像将被推送到配置的仓库。

###2.Docker部署###

[root@server1 ~]# cd /etc/yum.repos.d/
[root@server1 yum.repos.d]# vim docker.repo
[docker]
name=docker-ce
baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/x86_64/stable/
gpgcheck=0[update]
name=centos
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/7/extras/x86_64/
gpgcheck=0安装docker-ce
[root@server1 yum.repos.d]# yum install -y docker-ce启动服务
[root@server1 ~]# systemctl  enable --now docker[root@server1 ~]# docker info
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled  ##若出现这两个警告需要激活内核选项激活内核选项
[root@server1 ~]# vim /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1[root@server1 ~]# sysctl --system
[root@server1 ~]# systemctl  restart docker

启动容器
[root@server1 ~]# docker run -d --name web1 -p 80:80 nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
3f9582a2cbe7: Pull complete
9a8c6f286718: Pull complete
e81b85700bc2: Pull complete
73ae4d451120: Pull complete
6058e3569a68: Pull complete
3a1b8f201356: Pull complete
Digest: sha256:aa0afebbb3cfa473099a62c4b32e9b3fb73ed23f2a75a65ce1d4b4f55a5c2ef2
Status: Downloaded newer image for nginx:latest
0ab8d0e38142e97b8c611b156d723b2546fc1623909b65a0f5f016d8a2a1668d显示激活的容器
[root@server1 ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                               NAMES
0ab8d0e38142   nginx     "/docker-entrypoint.…"   8 seconds ago   Up 7 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   web1访问网页:http://192.168.56.11/

删除容器
[root@server1 ~]# docker rm -f web1查询镜像
[root@server1 ~]# docker search yakexi007拉取镜像到本地
[root@server1 ~]# docker pull yakexi007/game2048启动容器
[root@server1 ~]# docker run -d --name web1 -p 80:80 yakexi007/game2048访问网页:http://192.168.56.11/

###3.Docker镜像### 

(1)镜像的分层结构

• 共享宿主机的kernel

• base镜像提供的是最小的Linux发行版

• 同一docker主机支持运行多种Linux发行版

• 采用分层结构的最大好处是:共享资源

• Copy-on-Write 可写容器层

• 容器层以下所有镜像层都是只读的

• docker从上往下依次查找文件

• 容器层保存镜像变化的部分,并不会对镜像本身进行任何修改

• 一个镜像最多127层

(2)镜像常用子命令 

• images 显示镜像列表
• history 显示镜像构建历史
• commit 从容器创建镜像
• build 从Dockerfile构建镜像
• tag 给镜像打标签
• search 搜索镜像
• pull 从仓库拉取镜像
• push 上传镜像到仓库
• rmi 删除镜像

(3)镜像构建 

docker commit

docker commit 构建新镜像三部曲
运行容器
修改容器
将容器保存为新的镜像
缺点:
效率低、可重复性弱、容易出错
使用者无法对镜像进行审计,存在安全隐患
[root@server1 ~]# docker pull busybox   ##拉取一个小的镜像用来做测试
Using default tag: latest
latest: Pulling from library/busybox
ec562eabd705: Pull complete
Digest: sha256:9ae97d36d26566ff84e8893c64a6dc4fe8ca6d1144bf5b87b2b85a32def253c7
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest[root@server1 ~]# docker run -it --name demo busybox  ##交互式进入容器
/ # touch file1
/ # touch file2
ctrl+d: 退出容器后容器自动关闭
ctrl+pq: 退出容器后继续在后台运行显示所有容器,包括被停掉的
[root@server1 ~]# docker ps -a启动容器
[root@server1 ~]# docker start  demo进入容器
[root@server1 ~]# docker attach  demo提交容器变更到新的镜像
[root@server1 ~]# docker commit -m "add files" demo demo:v1[root@server1 ~]# docker history demo:v1
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
2b25ea847e4e   9 seconds ago   sh                                              39B       add files
827365c7baf1   13 days ago     /bin/sh -c #(nop)  CMD ["sh"]                   0B
<missing>      13 days ago     /bin/sh -c #(nop) ADD file:3f2f2548e5ddec788…   4.86MB这种方式不利于安全审计删除镜像
[root@server1 docker]# docker rmi demo:v1

 ②Dockerfile

dockerfile常用指令

• FROM

指定base镜像,如果本地不存在会从远程仓库下载。

• MAINTAINER

设置镜像的作者,比如用户邮箱等。

• COPY

把文件从build context复制到镜像

支持两种形式:COPY src dest 和 COPY ["src", "dest"]

src必须指定build context中的文件或目录

• ADD

用法与COPY类似,不同的是src可以是归档压缩文件,文件会被自动解压到dest, 也可以自动下载URL并拷贝到镜像:

ADD html.tar /var/www

ADD http://ip/html.tar /var/www

• ENV

设置环境变量,变量可以被后续的指令使用:

ENV HOSTNAME sevrer1.example.com

• EXPOSE

如果容器中运行应用服务,可以把服务端口暴露出去:

EXPOSE 80

• VOLUME

申明数据卷,通常指定的是应用的数据挂在点:

VOLUME ["/var/www/html"]

• WORKDIR

为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当 前工作目录,如果目录不存在会自动创建。

• RUN

在容器中运行命令并创建新的镜像层,常用于安装软件包:

RUN yum install -y vim

• CMD 与 ENTRYPOINT

这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker run后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会被执行。

docker run后面的参数可以传递给ENTRYPOINT指令当作参数。

Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后一个有效。

• Shell和exec格式的区别 

# cat Dockerfile

FROM busybox

ENV name world

ENTRYPOINT echo "hello, $name"

Shell格式底层会调用/bin/sh -c来执行命令,可以解析变量,而下面的 exec格式不会:

# cat Dockerfile

FROM busybox

ENV name world

ENTRYPOINT ["/bin/echo", "hello, $name"]

需要改写成以下形式:

# cat Dockerfile

FROM busybox

ENV name world

ENTRYPOINT ["/bin/sh", "-c", "echo hello, $name"]

Exec格式时,ENTRYPOINT可以通过CMD提供额外参数,CMD的额 外参数可以在容器启动时动态替换。在shell格式时ENTRYPOINT会忽 略任何CMD或docker run提供的参数。

# cat Dockerfile

FROM busybox

ENTRYPOINT ["/bin/echo", "hello"]

CMD ["world"]

看下在运行容器时的区别:

# docker run --rm busybox:v1

hello world

# docker run --rm busybox:v1 linux

hello linux

官方推荐使用exec格式书写

一个简单dockerfile 

配置nginx服务dockerfile 
[root@server1 ~]# mdkir docker
[root@server1 ~]# cd docker/
[root@server1 docker]#  cp ~/nginx-1.23.3.tar.gz .
[root@server1 docker]# vim Dockerfile
FROM centos:7
ADD nginx-1.23.3.tar.gz /mnt
WORKDIR /mnt/nginx-1.23.3
RUN yum install -y gcc make pcre-devel openssl-devel
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --with-http_ssl_module --with-http_stub_status_module
RUN make
RUN make install
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]构建镜像
[root@server1 docker]# docker build -t webserver:v1 .[root@server1 docker]# docker images webserver
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
webserver    v1        bfd6774cc216   8 seconds ago   494MB[root@server1 docker]# docker history  webserver:v1清理所有停止的容器
[root@server1 docker]# docker container prune启动容器
[root@server1 docker]# docker run -d --name web1 webserver:v1
查看容器详情
[root@server1 docker]# docker inspect  web1
访问容器
[root@server1 docker]# curl 172.17.0.2

###4.Docker镜像优化### 

选择最精简的基础镜像
减少镜像的层数
清理镜像构建的中间产物
注意优化网络请求
尽量去用构建缓存
使用多阶段构建镜像

(1)缩短镜像层

[root@server1 docker]# vim Dockerfile
FROM centos:7 as build
ADD nginx-1.23.3.tar.gz /mnt
WORKDIR /mnt/nginx-1.23.3
RUN yum install -y gcc make pcre-devel openssl-devel && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module --with-http_stub_status_module && make && make install && cd .. && rm -fr nginx-1.23.3 && yum clean all
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"][root@server1 docker]# docker build -t webserver:v2 .[root@server1 docker]# docker images  webserver
REPOSITORY   TAG       IMAGE ID       CREATED             SIZE
webserver    v2        caf0f80f2332   4 seconds ago       317MB
webserver    v1        bfd6774cc216   About an hour ago   494MB

(2)多阶段构建

[root@server1 docker]# vim Dockerfile
FROM centos:7 as build
ADD nginx-1.23.3.tar.gz /mnt
WORKDIR /mnt/nginx-1.23.3
RUN yum install -y gcc make pcre-devel openssl-devel && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module --with-http_stub_status_module && make && make install && cd .. && rm -fr nginx-1.23.3 && yum clean allFROM centos:7
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"][root@server1 docker]# docker build -t webserver:v3 .[root@server1 docker]# docker images  webserver
REPOSITORY   TAG       IMAGE ID       CREATED             SIZE
webserver    v3        1ac964f2cefe   29 seconds ago      205MB
webserver    v2        caf0f80f2332   3 minutes ago       317MB
webserver    v1        bfd6774cc216   About an hour ago   494MB

(3)使用最精简的基础镜像

导入基础镜像
[root@server1 ~]# docker load -i base-debian12.tar[root@server1 ~]# mkdir new
[root@server1 ~]# cd new/
[root@server1 new]# vim Dockerfile
FROM nginx:latest as base# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
ARG TIME_ZONERUN mkdir -p /opt/var/cache/nginx && \cp -a --parents /usr/lib/nginx /opt && \cp -a --parents /usr/share/nginx /opt && \cp -a --parents /var/log/nginx /opt && \cp -aL --parents /var/run /opt && \cp -a --parents /etc/nginx /opt && \cp -a --parents /etc/passwd /opt && \cp -a --parents /etc/group /opt && \cp -a --parents /usr/sbin/nginx /opt && \cp -a --parents /usr/sbin/nginx-debug /opt && \cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \cp -a --parents /usr/lib/x86_64-linux-gnu/libpcre* /opt && \cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtimeFROM gcr.io/distroless/base-debian11COPY --from=base /opt /EXPOSE 80 443ENTRYPOINT ["nginx", "-g", "daemon off;"][root@server1 new]# docker build -t webserver:v4 .[root@server1 new]# docker images  webserver
REPOSITORY   TAG       IMAGE ID       CREATED             SIZE
webserver    v4        c0c4e1d49f3d   4 seconds ago       34MB
webserver    v3        1ac964f2cefe   12 minutes ago      205MB
webserver    v2        caf0f80f2332   15 minutes ago      317MB
webserver    v1        bfd6774cc216   About an hour ago   494MB[root@server1 new]# docker run -d --name web1  webserver:v4[root@server1 new]# curl  172.17.0.2

###5.Docker仓库### 

• Docker 仓库是用来包含镜像的位置, Docker 提供一个注册服务器 (Register )来保存多个仓库,每个仓库又可以包含多个具备不同 tag 的镜像。
• Docker 运行中使用的默认仓库是 Docker Hub 公共仓库。

(1)Docker Hub 

首先注册账号 : https://hub.docker.com/

创建仓库

客户端登录docker hub
[root@server1 ~]# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: yakexi007		#docker hub注册的用户
Password: ****				#密码
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded上传镜像
[root@server1 ~]# docker tag webserver:v4 yakexi007/webserver:v4[root@server1 ~]# docker push yakexi007/webserver:v4
The push refers to repository [docker.io/yakexi007/webserver]
bbed3d4e37e0: Pushed
0b3d0512394d: Pushed
5b1fa8e3e100: Pushed
v4: digest: sha256:013969b9116df5dc77ddaef6c500129439e9db94f46b61b148b43e53900623e5 size: 949

(2)配置镜像加速器

docker hub 上下载镜像的速度太慢,需要配置镜像加速器,这里以阿里云为例
[root@server1 ~]# vim /etc/docker/daemon.json
{"registry-mirrors": ["https://registry.docker-cn.com"]   ##docker国内镜像源
}[root@server1 ~]# systemctl restart docker[root@server1 ~]# docker info

(3)registry私有仓库

docker hub虽然方便,但是还是有限制

• 需要internet连接,速度慢

• 所有人都可以访问

• 由于安全原因企业不允许将镜像放到外网

好消息是docker公司已经将registry开源,我们可以快速构建企业私有仓库

官网:https://docs.docker.com/registry/deploying/

拉取registry镜像
[root@server1 ~]# docker pull registry
运行registry仓库
[root@server1 docker]# docker run -d -p 5000:5000 --restart=always --name registry registry上传镜像
[root@server1 ~]# docker tag nginx:latest localhost:5000/nginx:latest
[root@server1 ~]# docker push localhost:5000/nginx[root@server1 ~]# curl  localhost:5000/v2/_catalog
{"repositories":["nginx"]}下载镜像
[root@server1 ~]# docker pull localhost:5000/nginx

(4)insecure registry配置非加密端口

本地搭建好私有仓库后,要验证其他主机是否能远程下载仓库里的镜像

默认情况下用的是https,不能直接下载

需要配置非加密端口强制让其他主机使用非加密的仓库

先给远程主机server2配置docker-ce服务

 强制让远程主机访问非加密的私有仓库

配置使用非加密端口
[root@server2 ~]# vim /etc/docker/daemon.json
{"insecure-registries" : ["http://192.168.56.11:5000"]
}[root@server2 docker]# systemctl  restart docker拉取镜像
[root@server2 docker]# docker pull 192.168.56.11:5000/nginx

(5)仓库加密 

加密部署

升级软件包
[root@server1 ~]# yum install -y openssl11-1.1.1k-4.el7.x86_64.rpm openssl11-libs-1.1.1k-4.el7.x86_64.rpm添加域名解析
[root@server1 ~]# vim /etc/hosts
...
192.168.56.11   server1 reg.westos.org[root@server1 ~]# mkdir certs
[root@server1 ~]# openssl11 req -newkey rsa:4096 -nodes -sha256 -keyout certs/westos.org.key -addext "subjectAltName = DNS:reg.westos.org" -x509 -days 365 -out certs/westos.org.crt启动容器
[root@server1 ~]# docker run -d --restart=always --name registry
-p 443:443    ##-p做端口映射 
-v /opt/registry:/var/lib/registry 
-v /root/certs:/certs     ##-v把冒号前的目录挂载在容器内的冒号后的目录
-e REGISTRY_HTTP_ADDR=0.0.0.0:443    ##registry的http监听443端口
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/westos.org.crt   ##证书的访问位置
-e REGISTRY_HTTP_TLS_KEY=/certs/westos.org.key   ##key的访问位置
registry   ##镜像部署客户端证书,不然会报错
[root@server1 ~]# docker tag nginx:latest reg.westos.org/nginx:latest
[root@server1 ~]# docker push reg.westos.org/nginx:latest                                                                                             The push refers to repository [reg.westos.org/nginx]
Get "https://reg.westos.org/v2/": x509: certificate signed by unknown authority[root@server1 ~]# mkdir -p /etc/docker/certs.d/reg.westos.org/
[root@server1 ~]# cp /root/certs/westos.org.crt /etc/docker/certs.d/reg.westos.org/ca.crt验证[root@server1 ~]# docker push reg.westos.org/nginx:latest[root@server1 reg.westos.org]# curl -k https://reg.westos.org/v2/_catalog
{"repositories":["nginx"]}

远程主机使用测试 

server2上移除非安全仓库设置
[root@server2 docker]# mv daemon.json  /mnt/
[root@server2 docker]# systemctl  restart docker添加解析
[root@server2 ~]# vim /etc/hosts
...
192.168.56.11   server1 reg.westos.org拷贝证书
[root@server1 ~]# cd /etc/docker/
[root@server1 ~]# scp -r certs.d/ server2:/etc/docker/远程拉取server1仓库中镜像
[root@server2 ~]# docker pull reg.westos.org/nginx
Using default tag: latest
latest: Pulling from nginx
Digest: sha256:c94f3436f3bfcb467e9723bdb4957e2e86c00cc5f21e38a40d668c1a4c324696
Status: Downloaded newer image for reg.westos.org/nginx:latest
reg.westos.org/nginx:latest

(6) 仓库认证

[root@server1 ~]# yum install -y httpd-tools
[root@server1 ~]# mkdir auth
[root@server1 ~]# htpasswd -Bc auth/htpasswd admin
New password:
Re-type new password:
Adding password for user admin第二次添加不要加“-c”选项,不然会覆盖
[root@server1 ~]# htpasswd -B auth/htpasswd wxh
New password:
Re-type new password:
Adding password for user wxh[root@server1 ~]# cat auth/htpasswd
admin:$2y$05$Wm2LHttPY5a6i2KMG0fShe92d/PjnaBbGitiClcE3wqHmwO8dIDFm
wxh:$2y$05$9rE9CXyZ1fdcMammhh7f6.soDHgKdSsi0DXBgkRW5sKRw5sEJo1lK删除registry,重建
[root@server1 ~]# docker rm -f registry
[root@server1 ~]# docker run -d -p 443:443 --restart=always --name registry -v /opt/registry:/var/lib/registry -v /root/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/westos.org.crt -e REGISTRY_HTTP_TLS_KEY=/certs/westos.org.key -v /root/auth:/auth -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registry登录仓库,不然无法上传下载
[root@server1 ~]# docker login reg.westos.org
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded
[root@server1 ~]# cat .docker/config.json
{"auths": {"reg.westos.org": {"auth": "YWRtaW46d2VzdG9z"}}
}验证
[root@server1 ~]# docker tag busybox:latest reg.westos.org/busybox:latest
[root@server1 ~]# docker push reg.westos.org/busybox:latest[root@server1 ~]# curl -k https://reg.westos.org/v2/_catalog  -u admin:westos
{"repositories":["busybox","nginx"]}登出
[root@server1 ~]# docker logout reg.westos.org

远程主机下载镜像
首先登录仓库
[root@server2 ~]# docker login reg.westos.org
Username: lfj
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded
拉取
[root@server2 ~]# docker pull reg.westos.org/busybox
Using default tag: latest
latest: Pulling from busybox
d0f42ecf7e6c: Pull complete
Digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b
Status: Downloaded newer image for reg.westos.org/busybox:latest
reg.westos.org/busybox:latest

 (7)harbor企业级私有仓库

①仓库部署

删除之前部署的registry,不然会冲突
[root@server1 ~]# docker rm -f registry[root@server1 ~]# tar zxf harbor-offline-installer-v2.5.0.tgz
[root@server1 ~]# cd harbor/
[root@server1 harbor]# cp harbor.yml.tmpl harbor.yml
[root@server1 harbor]# vim harbor.yml
hostname: reg.westos.orghttp:# port for http, default is 80. If https enabled, this port will redirect to https portport: 80https:# https port for harbor, default is 443port: 443# The path of cert and key files for nginxcertificate: /data/certs/westos.org.crtprivate_key: /data/certs/westos.org.key...
harbor_admin_password: westos拷贝证书
[root@server1 ~ ]# mkdir /data
[root@server1 ~ ]# cp -r certs /data部署docker-compose
[root@server1 ~]# mv docker-compose-linux-x86_64-v2.5.0 /usr/local/bin/docker-compose
[root@server1 ~]# chmod +x /usr/local/bin/docker-compose部署harbor
[root@server1 harbor]# ./install.sh

使用浏览器登录仓库 用户名:admin 密码是上面配置文件设置的westos

https://192.168.76.11

②仓库管理 

上传镜像
上传镜像,首先需要执行docker login reg.westos.org,此处已经执行过[root@server1 ~]# docker tag busybox:latest reg.westos.org/library/busybox:latest
[root@server1 ~]# docker tag nginx:latest reg.westos.org/library/nginx:latest[root@server1 ~]# docker push reg.westos.org/library/nginx:latest
[root@server1 ~]# docker push reg.westos.org/library/busybox:latest

拉取镜像 

 远程主机拉取镜像时,需要先配置默认仓库

配置默认仓库
[root@server2 ~]# vim /etc/docker/daemon.json
{"registry-mirrors": ["https://reg.westos.org"]
}[root@server2 ~]# systemctl  restart dockerlibrary项目中的镜像下载时可以直接写镜像名称
[root@server2 ~]# docker pull nginx

 

私有仓库管理

创建私有仓库

 新建用户

授权新建的用户可以维护私有仓库

私有仓库上传下载都需要认证,并且还要指定仓库域名  

[root@server1 ~]# docker tag ubuntu:latest reg.westos.org/westos/ubuntu:latest
[root@server1 ~]# docker push reg.westos.org/westos/ubuntu:latest[root@server2 ~]# docker login reg.westos.org
Username: wxh
Password: ***[root@server2 ~]# docker pull reg.westos.org/westos/ubuntu

仓库附加说明

harbor仓库docker-compose在每次主机重启时会开机自启,但经常有某个容器没能自启的情况发生,使harbor产生异常,因此每次重启后手动运行一下docker-compose start

[root@server1 harbor]# docker-compose down  #删除harbor仓库,停止所有容器并全部删除,但是挂载数据不会消失
[root@server1 harbor]# docker-compose logs  #查看日志添加新模块部署harbor
[root@server1 harbor]# ./install.sh --with-chartmuseum

###6.Docker网络###

docker network子命令

• connect 连接容器到指定网络

• create 创建网络

• disconnect 断开容器与指定网络的连接

• inspect 显示指定网络的详细信息

• ls 显示所有网络

• rm 删除网络

(1)原生网络

docker的镜像是令人称道的地方,但网络功能还是相对薄弱的部分。

docker安装后会自动创建3种网络:bridge、host、none

可以使用以下命令查看
[root@server1 harbor]# docker network  ls
NETWORK ID     NAME      DRIVER    SCOPE
fe748c728e1e   bridge    bridge    local
ef483e4d5ab4   host      host      local
0a4064c6ebb6   none      null      local

①bridge

docker安装时会创建一个名为 docker0 的Linux bridge,新建的容器会自动桥接到这个接口。

bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的。

容器通过宿主机的NAT规则后可以访问外网。

默认使用桥接模式,桥接到docker0上
[root@server1 ~]# docker run -d --name demo  nginx
[root@server1 ~]# yum install -y bridge-utils
[root@server1 ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242ea04cb8d       no              veth6725905

②host

host 网络模式需要在容器创建时指定 --network=host
host模式可以让容器共享宿主机网络栈,不会新建虚拟网卡,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。

host模式,容器和宿主机共享同一网络栈,不会新建虚拟网卡
[root@server1 ns]# docker run -it --rm --network host busybox

host模式下不能同时运行两次同一个容器,会发生冲突

因为共用一个网络栈,端口资源也是共用的

③none 

none模式是指禁用网络功能,只有lo接口,在容器创建时使用 --network=none指定。

none禁用网络,只用回环接口
[root@server1 harbor]# docker run -it --rm --network none busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
/ #

(2)自定义网络 

自定义网络模式,docker提供了三种自定义网络驱动:

• bridge

• overlay

• macvlan

bridge驱动类似默认的bridge网络模式,但增加了一些新的功能,overlay和macvlan是用于创建跨主机网络。

建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。

①自定义网络 

自定义网络
docker network  create my_net1
查看
[root@server1 ~]# docker network inspect my_net1

②自定义网络段

自定义网络地址段
[root@k8s1 ~]# docker network  create --subnet 10.0.0.0/24 --gateway 10.0.0.1 my_net2
查看
[root@server1 ~]# docker network inspect my_net2

③自定义网络内嵌DNS解析 

使用--ip参数可以指定容器ip地址,但必须是在自定义网桥上,默认的 bridge模式不支持,同一网桥上的容器是可以互通的。

桥接到不同网桥上的容器,彼此是不通信的。

docker在设计上就是要隔离不同network的

那么如何使两个不同网桥的容器通信呢:

使用 docker network connect命令为vm1添加一块my_net2 的网卡。

自定义网络内嵌dns解析同一网桥上的容器是可以互通的
[root@server1 ~]# docker run -d --name web1 --network my_net1 nginx
[root@server1 ~]# docker run -it --rm --network my_net1 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
97: eth0@if98: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueuelink/ether 02:42:ac:14:00:03 brd ff:ff:ff:ff:ff:ffinet 172.20.0.3/16 brd 172.20.255.255 scope global eth0valid_lft forever preferred_lft forever
/ # ping web1
PING web1 (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.076 ms
64 bytes from 172.20.0.2: seq=1 ttl=64 time=0.064 ms
64 bytes from 172.20.0.2: seq=2 ttl=64 time=0.062 ms不同网络之间是被隔离的,默认不能通信
[root@server1 ~]# docker run -it --rm --network my_net2 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
85: eth0@if86: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueuelink/ether 02:42:0a:00:00:02 brd ff:ff:ff:ff:ff:ffinet 10.0.0.2/24 brd 10.0.0.255 scope global eth0valid_lft forever preferred_lft forever/ # ping web1
ping: bad address 'web1'不同网络之间的通信需要附加虚拟网卡
[root@server1 ~]# docker run -it --rm --network my_net2  --name demo busybox
/ # ping web1
ping: bad address 'web1'ctrl+pq 快捷键退出容器终端把demo接入到my_net1网络
[root@server1 ~]# docker network  connect my_net1 demo再进入容器
[root@server1 ~]# docker attach demo
/ # ping web1
PING web1 (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.079 ms

 (3)Docker容器通信

①joined容器

Joined容器一种较为特别的网络模式

在容器创建时使用--network=container:vm1指定(vm1指定的是运行的容器名)

处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost 高效快速通信。
由于共享同一份网络栈,所以joined模式不能用启动同一个容器,会发生冲突

两个容器共享一个网络栈
[root@server1 ~]# docker run -it --rm --network container:web1 --name web2 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
19: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueuelink/ether 02:42:ac:14:00:02 brd ff:ff:ff:ff:ff:ffinet 172.20.0.2/16 brd 172.20.255.255 scope global eth0valid_lft forever preferred_lft forever

 ②--link

--link 可以用来链接2个容器

--link的格式:

--link <name or id>:alias

name和id是源容器的name和id,alias是源容器在link下的别名。

现在不常用,了解即可

[rootaserver1~l#docker run -d nginx 
d61a3e7613f9417d29cc97666a80186758581e5f4b067c1de7014ef755ee9ba2
[rootaserver1~]#docker ps
CONTAINER ID    IMAGE    COMMAND   CREATED   PORTS   NAMES
d61a3e7613f93   nginx   "nginx-g'daemon of."   3seconds ago    80/tcp    hopeful golick[root@server1 ~]# docker run -it --name ml --link hopeful golick:web ubuntu
roota137597ff4039:/#ping web
PING web(172.17.0.2)56(84)bytes of data.
64 bytes from web(172.17.0.2):icmp seg=l ttl=64 time=0.054 ms
64 bytes from web(172.17.0.2):icmp seg=2 ttl=64 time=0.036 ms

 ③容器访问外网

容器如何访问外网是通过iptables的SNAT实现的

 ④外部主机访问容器

外网如何访问容器:

• 端口映射

• -p 选项指定映射端口

外网访问容器用到了docker-proxy和iptables DNAT(双重保障)

• 宿主机访问本机容器使用的是iptables DNAT

• 外部主机访问容器或容器之间的访问是docker-proxy实现

外部主机访问容器可以通过DNAT规则和docker-proxy,只要有一种正常就能通信
[root@server1 ~]# docker rm -f web1
[root@server1 ~]# docker run -d --name web1 -p 80:80 nginx
[root@server1 ~]# iptables -t nat -nL
...
Chain POSTROUTING (policy ACCEPT)	#容器访问外网通过SNAT策略
target     prot opt source               destination
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0
MASQUERADE  all  --  172.21.0.0/16        0.0.0.0/0
MASQUERADE  all  --  10.0.0.0/24          0.0.0.0/0
MASQUERADE  all  --  172.20.0.0/16        0.0.0.0/0
MASQUERADE  tcp  --  172.17.0.2           172.17.0.2           tcp dpt:80Chain DOCKER (2 references)
target     prot opt source               destination
RETURN     all  --  0.0.0.0/0            0.0.0.0/0
RETURN     all  --  0.0.0.0/0            0.0.0.0/0
RETURN     all  --  0.0.0.0/0            0.0.0.0/0
RETURN     all  --  0.0.0.0/0            0.0.0.0/0
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:172.17.0.2:80	#DNAT规则

DNAT规则和docker-proxy策略任何一个down掉,另一个会自动起作用,两个都在时外部访问优先走docker-proxy

重启容器后,DNAT规则和docker-proxy策略会自动恢复

 ⑤跨主机容器通信

跨主机网络解决方案

• docker原生的overlay和macvlan

• 第三方的flannel、weave、calico

众多网络方案是如何与docker集成在一起的

• libnetwork docker容器网络库

• CNM (Container Network Model)这个模型对容器网络进行了抽象

CNM分三类组件

• Sandbox:容器网络栈,包含容器接口、dns、路由表。 (namespace)

• Endpoint:作用是将sandbox接入network (veth pair)

• Network:包含一组endpoint,同一network的endpoint可以通信。

macvlan 网络方案实现
• Linux kernel 提供的一种网卡虚拟化技术。
无需 Linux bridge ,直接使用物理接口,性能极好。

在两台docker主机上各添加一块网卡

开启混杂模式并激活
[root@server1 ~]# ip link  set eth1  promisc on
[root@server1 ~]# ip link set up eth1创建macvlan网络
[root@server1 ~]# docker network  create -d macvlan --subnet 10.0.0.0/24 --gateway 10.0.0.1 -o parent=eth1 macvlan1用创建的网络运行容器
[root@server1 ~]# docker run -it --rm --network macvlan1 --ip 10.0.0.11 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
108: eth0@if107: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueuelink/ether 02:42:0a:00:00:0b brd ff:ff:ff:ff:ff:ffinet 10.0.0.11/24 brd 10.0.0.255 scope global eth0server2上以此类推
[root@server2 ~]# ip link set eth1 promisc on
[root@server2 ~]# ip link set up eth1[root@server2 ~]# docker network  create -d macvlan --subnet 10.0.0.0/24 --gateway 10.0.0.1 -o parent=eth1 macvlan1[root@server2 ~]# docker run -it --rm --network macvlan1 --ip 10.0.0.12 busybox
i/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
9: eth0@if8: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueuelink/ether 02:42:0a:00:00:0c brd ff:ff:ff:ff:ff:ffinet 10.0.0.12/24 brd 10.0.0.255 scope global eth0valid_lft forever preferred_lft forever
/ # ping 10.0.0.11
PING 10.0.0.11 (10.0.0.11): 56 data bytes
64 bytes from 10.0.0.11: seq=0 ttl=64 time=1.117 ms
64 bytes from 10.0.0.11: seq=1 ttl=64 time=1.366 ms

server2以此类推

macvlan网络结构分析

• 没有新建linux bridge

• 容器的接口直接与主机网卡连接,无需NAT或端口映射。

macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络

• vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取 值为1~4094。

macvlan网络间的隔离和连通

• macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的。

• 可以在三层上通过网关将macvlan网络连通起来。

• docker本身不做任何限制,像传统vlan网络那样管理即可。

###7.Docke数据卷###

为什么要用数据卷

docker分层文件系统

• 性能差

• 生命周期与容器相同

docker数据卷

• mount到主机中,绕开分层文件系统

• 和主机磁盘性能相同,容器删除后依然保留

• 仅限本地磁盘,不能随容器迁移

docker提供了两种卷:

• bind mount

• docker managed volume

bind mount docker managed volume 对比
相同点:两者都是 host 文件系统中的某个路径。
• 不同点:

(1)数据卷管理

①bind mount

是将主机上的目录或文件mount到容器里。

使用直观高效,易于理解。

使用 -v 选项指定路径,格式 <host path>:<container path>

# docker run -d --name web -v /opt/website:/usr/share/nginx/html nginx

bind mount 默认权限是读写rw,可以在挂载时指定只读ro。

 -v选项指定的路径,如果不存在,挂载时会自动创建。

[root@server1 ~]# docker run -it --rm -v /tmp/data1:/data1 -v /tmp/data2:/data2:ro -v /etc/passwd:/mnt/passwd:ro busybox
/ # ls
bin    data1  data2  dev    etc    home   lib    lib64  mnt    proc   root   sys    tmp    usr    var
/ # cd /data1/
/data1 # ls
/data1 # touch file1
/data1 # ls
file1
/data1 # cd ..
/ # cd /data2/
/data2 # ls
/data2 # touch file2
touch: file2: Read-only file system
/data2 # cd /mnt/
/mnt # ls
passwd
/mnt # cat passwd

②docker managed volume 

bind mount必须指定host文件系统路径,限制了移植性。

docker managed volume 不需要指定mount源,docker自动为容器创建数 据卷目录。

默认创建的数据卷目录都在 /var/lib/docker/volumes 中。

如果挂载时指向容器内已有的目录,原有数据会被复制到volume中。

[root@server1 ~]# docker run -d --name web1 webserver:v3
[root@server1 ~]# docker inspect  web1
[root@server1 ~]# cd "/var/lib/docker/volumes/9e6528410eb82a00f89bd1eb5cdda034bb1fbbd0eab1aa36f5ec08fc521a5fae/_data"
[root@server1 _data]# ls
50x.html  index.html       ##docker managed volume 会复制目标挂载点的数据

查询docker managed volume
[root@server1 volumes]# docker volume  ls清理所有数据卷,在清理前需要先删除容器,释放对数据卷的占用
[root@server1 volumes]# docker volume  ls | grep -v DRIVER | awk '{system("docker volume rm "$2"")}'

创建数据卷
[root@server1 ~]# docker volume  create vol1
vol1
[root@server1 ~]# docker volume  ls
DRIVER    VOLUME NAME
local     vol1
[root@server1 ~]# docker volume  inspect vol1
[{"CreatedAt": "2023-03-05T09:21:01+08:00","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/vol1/_data","Name": "vol1","Options": null,"Scope": "local"}
]使用bind mount方式挂载数据卷,和docker managed volume结合在一起用
[root@server1 ~]# docker run -d --name web1 -v vol1:/usr/local/nginx/html webserver:v3还能在挂载时控制权限
[root@server1 ~]# docker rm -f web1
web1
[root@server1 ~]# docker run -d --name web1 -v vol1:/usr/local/nginx/html:ro webserver:v3共享卷
[root@server1 ~]# docker create -v /tmp/data1:/data1:rw -v /tmp/data2:/data2:ro -v /etc/passwd:/mnt/passwd:ro --name datavol busybox[root@server1 ~]# docker run -it --rm --volumes-from datavol busybox

(2)卷插件

docker 卷默认使用的是local类型的驱动,只能存在宿主机,跨主机的 volume就需要使用第三方的驱动,可以查看以下链接:

https://docs.docker.com/engine/extend/legacy_plugins/#volume - plugins

docker官方只提供了卷插件的api,开发者可以根据实际需求定制卷插件驱动。

https://docs.docker.com/engine/extend/plugins_volume/#volume - plugin-protocol

Docker Plugin 是以Web Service的服务运行在每一台Docker Host上的,通过HTTP协议传输RPC风格的JSON数据完成通信。

Plugin的启动和停止,并不归Docker管理,Docker Daemon依靠在缺省路径下查找UnixSocket文件,自动发现可用的插件。

当客户端与Daemon交互,使用插件创建数据卷时,Daemon会在后端 找到插件对应的socket 文件,建立连接并发起相应的API请求,最终结合Daemon自身的处理完成客户端的请求。

###8.Docker安全### 

(1)理解Docker安全

Docker容器的安全性,很大程度上依赖于Linux系统自身,评估Docker 的安全性时,主要考虑以下几个方面:

• Linux内核的命名空间机制提供的容器隔离安全

• Linux控制组机制对容器资源的控制能力安全。

• Linux内核的能力机制所带来的操作权限安全

• Docker程序(特别是服务端)本身的抗攻击性。

• 其他安全增强机制对容器安全性的影响。

①命名空间隔离的安全

• 当docker run启动一个容器时,Docker将在后台为容器创建一个独立的命名空间。命名空间提供了最基础也最直接的隔离。

• 与虚拟机方式相比,通过Linux namespace来实现的隔离不是那么彻底。

• 容器只是运行在宿主机上的一种特殊的进程,那么多个容器之间使用的就还是同一个宿主机的操作系统内核。

• 在 Linux 内核中,有很多资源和对象是不能被Namespace化的, 比如:时间。

②控制组资源控制的安全

• 当docker run启动一个容器时,Docker将在后台为容器创建一个独立的控制组策略集合。

• Linux Cgroups提供了很多有用的特性,确保各容器可以公平地分享主机的内存、CPU、磁盘IO等资源。

• 确保当发生在容器内的资源压力不会影响到本地主机系统和其他容器,它在防止拒绝服务攻击(DDoS)方面必不可少。

③内核能力机制

• 能力机制(Capability)是Linux内核一个强大的特性,可以提供细粒度的权限访问控制。

• 大部分情况下,容器并不需要“真正的”root权限,容器只需要少数的能力即可。

• 默认情况下,Docker采用“白名单”机制,禁用“必需功能”之外的其他权限。

④Docker服务端防护

• 使用Docker容器的核心是Docker服务端,确保只有可信的用户才能访问到Docker服务。

• 将容器的root用户映射到本地主机上的非root用户,减轻容器和主机之间因权限提升而引起的安全问题。

• 允许Docker 服务端在非root权限下运行,利用安全可靠的子进程来代理执行需要特权权限的操作。这些子进程只允许在特定范围内进行操作。

⑤其他安全特性

• 在内核中启用GRSEC和PAX,这将增加更多的编译和运行时的安全检查;并且通过地址随机化机制来避免恶意探测等。启用该特性不需要Docker进行任何配置。

• 使用一些有增强安全特性的容器模板。

• 用户可以自定义更加严格的访问控制机制来定制安全策略。

• 在文件系统挂载到容器内部时,可以通过配置只读模式来避免容器内的应用通过文件系统破坏外部环境,特别是一些系统运行状态相关的目录。

(2) 容器资源控制Linux Cgroups

Linux Cgroups 的全称是 Linux Control Group。

• 是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。

• 对进程进行优先级设置、审计,以及将进程挂起和恢复等操作。

Linux Cgroups 给用户暴露出来的操作接口是文件系统。

• 它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下。

• 执行此命令查看:mount -t cgroup

• 在 /sys/fs/cgroup 下面有很多诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统。

• 在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录)。

• 控制组下面的资源文件里填上什么值,就靠用户执行 docker run 时的 参数指定。

①CPU资源限制 

cpu_period 和 cpu_quota 这两个参数需要组合使用,用来限制进 程在长度为 cpu_period 的一段时间内,只能被分配到总量为 cpu_quota 的 CPU 时间,以上设置表示20%的cpu时间。

[root@server1 cpu]# docker run -it --rm --cpu-period 100000 --cpu-quota 20000 ubuntu   ###--cpu-period是cpu总分片 --cpu-quota是cpu配额 这里配额占总的20%
root@433a1612a171:/# dd if=/dev/zero of=/dev/null &

②CPU优先级

[root@server1 cpu]# docker run -it --rm  ubuntu
root@0280fc49f2d0:/# dd if=/dev/zero of=/dev/null &[root@server1 cpu]# docker run -it --rm --cpu-shares 100 ubuntu
root@b75b4d5066b8:/# dd if=/dev/zero of=/dev/null &测试时只保留一个cpu核心可用,只有争抢cpu资源时优先级才会生效
[root@server1 cpu1]# pwd
/sys/devices/system/cpu/cpu1
[root@server1 cpu1]# echo 0 > online

③内存资源限额

容器可用内存包括两个部分:

物理内存和swap交换分区。

• --memory设置内存使用限额

• --memory-swap设置swap交换分区限额

①用命令行控制内存限额
[root@server1 ~]# docker run -d --name demo --memory 200M --memory-swap=200M nginx②直接通过控制cgroup控制内存限额
创建一个容器目录
[root@server1 memory]# pwd
/sys/fs/cgroup/memory
[root@server1 memory]# mkdir x1
[root@server1 memory]# cd x1/
设置x1控制器的内存限额为200M
[root@server1 x1]# echo 209715200 > memory.limit_in_bytes[root@server1 x1]# yum install -y libcgroup-tools.x86_64
[root@server1 x1]# cd /dev/shm/
[root@server1 shm]# cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=300
[root@server1 shm]# free -mtotal        used        free      shared  buff/cache   available
Mem:           1980         187        1080         206         712        1389
Swap:          2047         103        1944
多出的100m会写入swap[root@server1 shm]# cd /sys/fs/cgroup/memory/x1/
设置x1控制器内存+swap分区限额一共为200M
[root@server1 x1]# echo 209715200 > memory.memsw.limit_in_bytes
[root@server1 x1]# cd -
/dev/shm
[root@server1 shm]# cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=300
Killed控制用户内存
[root@server1 shm]# useradd wxh
[root@server1 shm]# vim /etc/cgrules.conf
wxh     memory  x1/[root@server1 shm]# systemctl  start cgred.service
[root@server1 shm]# su - wxh
[wxh@server1 ~]$ cd /dev/shm/
[wxh@server1 shm]$ dd if=/dev/zero of=bigfile bs=1M count=200
Killed

④磁盘IO限制

--device-write-bps限制写设备的bps

目前的block IO限制只对direct IO有效。(不使用文件缓存)

[root@server1 ~]# docker run -it --rm --device-write-bps /dev/sda:30MB ubuntu
root@3226b0fc6231:/# dd if=/dev/zero of=bigfile bs=1M count=100 oflag=direct
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 3.31722 s, 31.6 MB/s

(3)Docker安全加固

①lxcfs安全隔离

利用LXCFS增强docker容器隔离性和资源可见性

[root@server1 ~]# yum install lxcfs-2.0.5-3.el7.centos.x86_64.rpm
[root@server1 ~]# lxcfs /var/lib/lxcfs &
[root@server1 ~]# docker run  -it -m 256m \
>       -v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \
>       -v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw \
>       -v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw \
>       -v /var/lib/lxcfs/proc/stat:/proc/stat:rw \
>       -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \
>       -v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \
>       ubuntu
root@45edbc92cc1d:/# free -mtotal        used        free      shared  buff/cache   available
Mem:             256           0         255           9           0         255
Swap:            256           0         256

②容器特权

设置特权级运行的容器:--privileged=true

• 有的时候我们需要容器具备更多的权限,比如操作内核模块,控制swap交 换分区,挂载USB磁盘,修改MAC地址等。

设置容器白名单:--cap-add

• --privileged=true 的权限非常大,接近于宿主机的权限,为了防止用户的滥用,需要增加限制,只提供给容器必须的权限。此时Docker 提供了权限白名单的机制,使用--cap-add添加必要的权限。

• capabilities手册地址: • http://man7.org/linux/man -pages/man7/capabilities.7.html

默认容器内的用户是受限的
[root@server1 ~]# docker run -it --rm busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueuelink/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ffinet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever
/ # id
uid=0(root) gid=0(root) groups=0(root),10(wheel)
/ # ip link set down eth0
ip: SIOCSIFFLAGS: Operation not permitted
/ # fdisk -l开启容器特权
[root@server1 ~]# docker run -it --rm --privileged busybox
/ # fdisk -l
Disk /dev/sda: 20 GB, 21474836480 bytes, 41943040 sectors
2610 cylinders, 255 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytesDevice  Boot StartCHS    EndCHS        StartLBA     EndLBA    Sectors  Size Id Type
/dev/sda1 *  0,32,33     130,170,40        2048    2099199    2097152 1024M 83 Linux
/dev/sda2    130,170,41  1023,254,63    2099200   41943039   39843840 18.9G 8e Linux LVM
Disk /dev/dm-0: 17 GB, 18249416704 bytes, 35643392 sectors
2218 cylinders, 255 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytesDisk /dev/dm-0 doesn't contain a valid partition table
Disk /dev/dm-1: 2048 MB, 2147483648 bytes, 4194304 sectors
261 cylinders, 255 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytesDisk /dev/dm-1 doesn't contain a valid partition table
/ # ip link set down eth0
/ # ip link set up eth0设置容器白名单
[root@server 1 ~]# docker run -it --rm --cap-add=NET_ADMIN busybox
/ # fdisk -l
/ # ip a a 10.0.0.1/24 dev eth0
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueuelink/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ffinet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft foreverinet 10.0.0.1/24 scope global eth0valid_lft forever preferred_lft forever
/ # ip a d 10.0.0.1/24 dev eth0
/ # ip a

安全加固的思路:

(1)保证镜像的安全

       • 使用安全的基础镜像

       • 删除镜像中的setuid和setgid权限

       • 启用Docker的内容信任

       • 最小安装原则

       • 对镜像进行安全漏洞扫描,镜像安全扫描器:Clair

       • 容器使用非root用户运行

(2)保证容器的安全

       • 对docker宿主机进行安全加固

       • 限制容器之间的网络流量

       • 配置Docker守护程序的TLS身份验证

       • 启用用户命名空间支持(userns-remap)

       • 限制容器的内存使用量

       • 适当设置容器CPU优先级

docker安全的遗留问题

(1)主要的内核子系统都没有命名空间,如:

       • SELinux

       • cgroup

       • 在/sys下的文件系统

       • /proc/sys, /proc/sysrq-trigger, /proc/irq, /proc/bus

(2)设备没有命名空间:

       • /dev/mem

       • /dev/sd*文件系统设备

       • 内核模块

 Docker安全的顶尖开源工具:

• Docker Bench for Security 对照安全基准审计Docker容器的脚本

• Clair API驱动的静态容器安全分析工具,拥有庞大的CVE数据库

• Cilium 内核层可感知API的网络和安全工具

• Anchore 使用CVE数据和用户定义的策略检查容器安全的工具

• OpenSCAP W orkbench 用于为各种平台创建和维护安全策略的环境

• Dagda 用于在Docker容器中扫描漏洞、特洛伊木马、病毒和恶意软件的工具

• Notary 使用服务器加强容器安全的框架,用于以加密方式委派责任

• Sysdig Falco 提供了行为活动监控,可深入了解容器

相关文章:

企业化运维(8)Docker容器技术

###1.Docker介绍### 什么是Docker Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的 Linux或Windows 机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之间…...

Unity C#底层原理(二)

委托 方法的容器&#xff1a;委托可以存储一个或多个方法的引用。可以使用委托对象来调用这些方法。函数/方法的变量类型&#xff1a;委托类型可以像变量一样声明和使用&#xff0c;存储方法的引用。存储、传递方法&#xff1a;委托可以作为参数传递给方法&#xff0c;也可以作…...

计算机网络-配置路由器ACL(访问控制列表)

配置访问控制列表ACL 拓扑结构 拓扑结构如下&#xff1a; 要配置一个ACL&#xff0c;禁止PC0访问PC3&#xff0c;禁止PC4访问PC0&#xff0c;其它正常。 配置Router0 配置接口IP地址&#xff1a; interface fastethernet 0/0 ip address 192.168.1.1 255.255.255.0 no shu…...

51单片机嵌入式开发:20、STC89C52R基于C51嵌入式点阵广告屏的设计

STC89C52R基于C51嵌入式点阵广告屏的设计 1 概述2 LED点阵介绍2.1 特点和优势2.2 工作原理&#xff1a;2.3 使用方法&#xff1a; 3 LED点阵原理3.1 Led点阵内部电路3.2 原理图电路3.3 74HC595 4 软件实现点阵图案的滑动4.1 软件工程代码4.2 Protues仿真 5 总结 配套示例程序 1…...

VLC输出NDI媒体流

目录 1. 下载安装VLC Play 2. 首先在电脑上安装NDI Tools 3. 运行VLC进行输出配置 4. 播放视频 5. 验证 (1)用Studio Monitor验证 (2)用OBS验证 NDI(Network Device Interface)即网络设备接口,是由美国 NewTek 公司开发的免费标准,它可使兼容的视频产品以高质量…...

WiFi 局域网通信 - 发现服务和解析

1. nsdManager nsdManager requireContext().getSystemService(Context.NSD_SERVICE) as NsdManager2. NsdManager.DiscoveryListener 注意&#xff1a;在onStartDiscoveryFailed 和 onStopDiscoveryFailed里不要调用nsdManager.stopServiceDiscovery(this) 方法&#xff0…...

ChatGPT建议前端学习计划

HTML&CSS基础 - 学习HTML标签、CSS属性、页面布局等基础知识 JavaScript基础 - 学习变量、数据类型、控制流、函数等基础知识 jQuery - 学习如何使用jQuery处理文档对象模型&#xff08;DOM&#xff09;、事件、动画等 Ajax - 全称为 Asynchronous JavaScript and XML&…...

YOLO5项目目录最强解析

YOLO5项目目录解析 YOLOv5 项目目录下的文件和目录的结构&#xff0c;以下是对每个目录和文件的解释&#xff1a; 目录 &#x1f4c1; .github: 存放 GitHub 相关配置和文件&#xff0c;如 GitHub Actions 工作流文件、Issue 模板等&#xff0c;用于自动化构建和持续集成等功…...

【python】sklearn基础教程及示例

【python】sklearn基础教程及示例 Scikit-learn&#xff08;简称sklearn&#xff09;是一个非常流行的Python机器学习库&#xff0c;提供了许多常用的机器学习算法和工具。以下是一个基础教程的概述&#xff1a; 1. 安装scikit-learn 首先&#xff0c;确保你已经安装了Python和…...

Linux:传输层(2) -- TCP协议(2)

目录 1. 流量控制 2. 滑动窗口 3. 拥塞控制 4. 延迟应答 5. 捎带应答 6. 面向字节流 7. 粘包问题 8. TCP异常情况 1. 流量控制 接收端处理数据的速度是有限的. 如果发送端发的太快 , 导致接收端的缓冲区被打满 , 这个时候如果发送端继续发送 , 就会造成丢包, 继而引…...

AcWing 802. 区间和

var说明add存储了插入操作&#xff0c;在指定 x x x下标所在位置 a [ x ] c a[x]c a[x]cquery是求 [ L , R ] [L,R] [L,R]区间和用到的数组,最后才用到alls 是存储离散化之后的值 , 对于会访问到的每个下标&#xff0c;统统丢到 a l l s 里面 &#xff0c;会把 x 和 [ L , R …...

实验2-2-1 温度转换

#include<stdio.h> #include <math.h> int main(){int c,f150;c5*(f-32)/9;printf("fahr 150, celsius %d",c); }...

Spark实时(六):Output Sinks案例演示

文章目录 Output Sinks案例演示 一、​​​​​​​File sink 二、​​​​​​​​​​​​​​Memory Sink 三、​​​​​​​​​​​​​​Foreach Sink 1、​​​​​​​foreachBatch 2、​​​​​​​​​​​​​​foreach Output Sinks案例演示 当我们对流式…...

在SQL编程中DROP、DELETE和TRUNCATE的区别

在SQL编程中&#xff0c;DROP、DELETE和TRUNCATE都是用于删除数据的命令&#xff0c;但它们之间有着显著的区别&#xff0c;主要体现在它们删除数据的范围、操作的不可逆性、对表结构的影响、性能以及事务日志的影响上。 DROP: 作用&#xff1a;DROP命令用于删除整个表及其所有…...

【AI大模型】Prompt 提示词工程使用详解

目录 一、前言 二、Prompt 提示词工程介绍 2.1 Prompt提示词工程是什么 2.1.1 Prompt 构成要素 2.2 Prompt 提示词工程有什么作用 2.2.1 Prompt 提示词工程使用场景 2.3 为什么要学习Prompt 提示词工程 三、Prompt 提示词工程元素构成与操作实践 3.1 前置准备 3.2 Pro…...

学习记录day18——数据结构 算法

算法的相关概念 程序 数据结构 算法 算法是程序设计的灵魂&#xff0c;结构式程序设计的肉体 算法&#xff1a;计算机解决问题的方法护额步骤 算法的特性 1、确定性&#xff1a;算法中每一条语句都有确定的含义&#xff0c;不能模棱两可 2、有穷性&#xff1a;程序执行一…...

一篇文章带你学完Java所有的时间与日期类

目录 一、传统时间与日期类 1.Date类 构造方法 获取日期和时间信息的方法 设置日期和时间信息的方法 2.Calendar类 主要特点和功能 常用方法 1. 获取当前日历对象 2. 获取日历中的某个信息 3. 获取日期对象 4. 获取时间毫秒值 5. 修改日历的某个信息 6. 为某个信息增…...

利用GPT4o Captcha工具和AI技术全面识别验证码

利用GPT4o Captcha工具和AI技术全面识别验证码 &#x1f9e0;&#x1f680; 摘要 GPT4o Captcha工具是一款命令行工具&#xff0c;通过Python和Selenium测试各种类型的验证码&#xff0c;包括拼图、文本、复杂文本和reCAPTCHA&#xff0c;并使用OpenAI GPT-4帮助解决验证码问…...

大学生算法高等数学学习平台设计方案 (第一版)

目录 目标用户群体的精准定位 初阶探索者 进阶学习者 资深研究者 功能需求的深度拓展 个性化学习路径定制 概念图谱构建 公式推导展示 交互式问题解决系统 新功能和创新点的引入 虚拟教室环境 数学建模工具集成 算法可视化平台 学术论文资源库 技术实现的前瞻性…...

机器学习算法与Python实战 | 两行代码即可应用 40 个机器学习模型--lazypredict 库!

本文来源公众号“机器学习算法与Python实战”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;两行代码即可应用 40 个机器学习模型 今天和大家一起学习使用 lazypredict 库&#xff0c;我们可以用一行代码在我们的数据集上实现许多…...

使用WebSocket协议调用群发方法将消息返回客户端页面

目录 一.C/S架构&#xff1a; 二.Http协议与WebSocket协议的区别&#xff1a; 1.Http协议与WebSocket协议的区别&#xff1a; 2.WebSocket协议的使用场景&#xff1a; 三.项目实际操作&#xff1a; 1.导入依赖&#xff1a; 2.通过WebSocket实现页面与服务端保持长连接&a…...

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第五十七章 Linux中断实验

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…...

每日一题~961div2A+B+C(阅读题,思维,数学log)

A 题意&#xff1a;给你 n*n 的表格和k 个筹码。每个格子上至多放一个 问至少占据多少对角线。 显然&#xff0c;要先 格数的多的格子去放。 n n-1 n-2 …1 只有n 的是一个&#xff08;主对角线&#xff09;&#xff0c;其他的是两个。 #include <bits/stdc.h> using na…...

Fireflyrk3288 ubuntu18.04添加Qt开发环境、安装mysql-server

1、创建一台同版本的ubuntu18.04的虚拟机 2、下载rk3288_ubuntu_18.04_armhf_ext4_v2.04_20201125-1538_DESKTOP.img 3、创建空img镜像容器 dd if/dev/zero ofubuntu_rootfs.img bs1M count102404、将该容器格式化成ext4文件系统 mkfs.ext4 ubuntu_rootfs.img5、将该镜像文件…...

简化mybatis @Select IN条件的编写

最近从JPA切换到Mybatis&#xff0c;使用无XML配置&#xff0c;Select注解直接写到interface上&#xff0c;发现IN条件的编写相当麻烦。 一般得写成这样&#xff1a; Select({"<script>","SELECT *", "FROM blog","WHERE id IN&quo…...

Windows图形界面(GUI)-MFC-C/C++ - Control

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 Control 资源编辑器 添加控件 设置控件属性 添加控件变量 添加消息处理 处理控件事件 控件焦点顺序 Control 资源编辑器 资源编辑器&#xff1a;用于可视化地编辑对话框和控件。…...

SQL Server数据库安全:策略制定与实践指南

SQL Server数据库安全&#xff1a;策略制定与实践指南 在当今数字化时代&#xff0c;数据安全是每个组织的核心关注点。SQL Server作为广泛使用的关系型数据库管理系统&#xff0c;提供了一套强大的安全特性来保护存储的数据。制定有效的数据库安全策略是确保数据完整性、可用…...

Spring Boot入门指南:留言板

一.留言板 1.输⼊留⾔信息,点击提交.后端把数据存储起来. 2.⻚⾯展⽰输⼊的表⽩墙的信息 规范&#xff1a; 1.写一个类MessageInfo对象&#xff0c;添加构造方法 虽然有快捷键&#xff0c;但是还是不够偷懒 项目添加Lombok。 Lombok是⼀个Java⼯具库&#xff0c;通过添加注…...

Docker 中安装和配置带用户名和密码保护的 Elasticsearch

在 Docker 中安装和配置带用户名和密码保护的 Elasticsearch 需要以下步骤。Elasticsearch 的安全功能&#xff08;包括基本身份验证&#xff09;在默认情况下是启用的&#xff0c;但在某些版本中可能需要手动配置。以下是详细步骤&#xff0c;包括如何设置用户名和密码。 1. …...

面试官:说说JVM内存调优及内存结构

1. JVM简介 JVM&#xff08;Java虚拟机&#xff09;是运行Java程序的平台&#xff0c;它使得Java能够跨平台运行。JVM负责内存的自动分配和回收&#xff0c;减轻了程序员的负担。 2. JVM内存结构 运行时数据区是JVM中最重要的部分&#xff0c;包含多个内存区域&#xff1a; …...

Ansible的脚本-----playbook剧本【下】

目录 实战演练六&#xff1a;tags 模块 实战演练七&#xff1a;Templates 模块 实战演练六&#xff1a;tags 模块 可以在一个playbook中为某个或某些任务定义“标签”&#xff0c;在执行此playbook时通过ansible-playbook命令使用--tags选项能实现仅运行指定的tasks。 playboo…...

Mysql开启远程控制简化版,亲测有效

首先关闭防火墙 改表法 打开上图的CMD&#xff0c;输入密码进入&#xff0c;然后输入一下指令 1.use mysql; 2.update user set host % where user root;//更新root用户的权限&#xff0c;允许任何主机连接 3.FLUSH PRIVILEGES;//刷新权限&#xff0c;使更改生效 具体参考…...

【MQTT协议与IoT通信】MQTT协议的使用和管理

MQTT协议与IoT通信&#xff1a;MQTT协议的使用和管理 目录 引言MQTT协议概述 什么是MQTTMQTT的工作原理 MQTT协议的关键特性 轻量级与高效性发布/订阅模式质量服务等级(QoS)持久会话安全性 MQTT协议的使用方法 设置MQTT Broker连接MQTT Client发布消息订阅主题断开连接 MQTT协…...

根据题意写出完整的css,html和js代码【购物车模块页面及功能实现】

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…...

AWS免费层之后:了解和管理您的云服务成本

Amazon Web Services (AWS) 为新用户提供了12个月的免费层服务&#xff0c;这是许多人开始使用云服务的绝佳方式。但是&#xff0c;当这一年结束后&#xff0c;您的AWS使用会如何变化&#xff1f;我们九河云通过本文将探讨免费层结束后的AWS成本情况&#xff0c;以及如何有效管…...

Linux定时同步系统时间到硬件时间

Linux定时同步系统时间到硬件时间 1. 系统时间、软件时间 系统时间 &#xff08;System Time&#xff09;&#xff1a; 一般说来就是我们执行 date命令看到的时间&#xff0c;linux系统下所有的时间调 用&#xff08;除了直接访问硬件时间的命令&#xff09;都是使用的这个时…...

网络编程——wireshark抓包、tcp粘包

目录 一、前言 1.1 什么是粘包 1.2 为什么UDP不会粘包 二、编写程序 文件树 客户端程序 服务器程序 tcp程序 头文件 makefile 三、 实验现象 四、改进实验 五、小作业 一、前言 最近在做网络芯片的驱动&#xff0c;验证功能的时候需要借助wireshark这个工具&…...

el-table合计行更新问题

说明&#xff1a;在使用el-table自带的底部合计功能时&#xff0c;初始界面不会显示合计内容 解决方案&#xff1a;使用 doLayout()方法 updated() {this.$nextTick(() > {this.$refs[inventorySumTable].doLayout();});},完整代码&#xff1a; // show-summary&#xff1a…...

ChatGPT:数据库不符合第二范式示例

ChatGPT&#xff1a;数据库不符合第二范式示例 这张图片为什么不符合数据库第二范式 这个表格不符合数据库第二范式&#xff08;2NF&#xff09;的原因如下&#xff1a; 1. 数据库第二范式&#xff08;2NF&#xff09;定义 第二范式要求一个数据库表格在满足第一范式&#xf…...

27、美国国家冰雪中心(NSIDC)海冰密集度月数据下载与处理

文章目录 一、前言二、数据下载三、使用Ponply查看数据结构四、代码一、前言 处理美国国家冰雪中心(NSIDC)的海冰密集度月度数据时,坐标转换是一个重要的步骤。NSIDC提供的数据通常采用极地球面坐标系,需要将其转换为常用的地理坐标系(如经纬度)以便进行分析和可视化。 坐…...

vite环境下使用bootstrap

环境 nodejs 18 pnpm 初始化 pnpm init pnpm add -D vite --registry http://registry.npm.taobao.org pnpm add bootstrap popperjs/core --registry http://registry.npm.taobao.org pnpm add -D sass --registry http://registry.npm.taobao.org新建vite.config.js cons…...

Laravel视图渲染封装

第一种 app/Helpers/ViewHelper.php 创建一个辅助函数&#xff0c;用于动态确定视图路径&#xff1a; <?php if (!function_exists(fetchView)) {function fetchView($data []){$currentAction \Route::currentRouteAction();list($controller, $method) explode(, $c…...

C++学习补充2:MySQL select 查询

MySQL select 查询 MySQL 查询 select时&#xff0c; 不区分大小写的。 MySQL 在默认情况下是区分大小写的&#xff0c;但是它的行为可能因配置和使用的字符集而有所不同。以下是一些可能导致查询在 SELECT 语句中不区分大小写的原因&#xff1a; 字符集设置&#xff1a;如果…...

uni-app声生命周期

应用的生命周期函数在App.vue页面 onLaunch:当uni-app初始化完成时触发&#xff08;全局触发一次&#xff09; onShow:当uni-app启动&#xff0c;或从后台进入前台时显示 onHide:当uni-app从前台进入后台 onError:当uni-app报错时触发,异常信息为err 页面的生命周期 onLoad…...

排序算法--堆排序

基本思想 堆排序的基本思想是&#xff0c;将待排序的元素构建成一个最大堆或最小堆。对于最大堆来说&#xff0c;堆顶是整个堆中的最大元素&#xff1b;对于最小堆来说&#xff0c;堆顶是整个堆中的最小元素。然后&#xff0c;将堆顶元素与堆中最后一个元素交换&#xff0c;并…...

iPhone 在 App Store 中推出的 PC 模拟器 UTM SE

PC 模拟器是什么&#xff1f;PC 模拟器是一种软件工具&#xff0c;它模拟不同硬件或操作系统环境&#xff0c;使得用户可以在一台 PC 上运行其他平台的应用程序或操作系统。通过 PC 模拟器&#xff0c;用户可以在 Windows 电脑上体验 Android 应用、在 Mac 电脑上运行 Windows …...

FastAPI删除mongodb重复数据(数据清洗)

在 FastAPI 中删除 MongoDB 重复数据&#xff0c;你需要结合使用 MongoDB 查询和 FastAPI 的路由功能。以下是一个通用的例子&#xff0c;演示如何删除特定字段上的重复数据&#xff1a; 1. 定义数据模型: from pydantic import BaseModel, Field from bson import ObjectId …...

移动UI:排行榜单页面如何设计,从这五点入手,附示例。

移动UI的排行榜单页面设计需要考虑以下几个方面&#xff1a; 1. 页面布局&#xff1a; 排行榜单页面的布局应该清晰明了&#xff0c;可以采用列表的形式展示排行榜内容&#xff0c;同时考虑到移动设备的屏幕大小&#xff0c;应该设计合理的滚动和分页机制&#xff0c;确保用户…...

如何解决 uni-app 项目中 “文件查找失败:‘crypto-js‘“ 的问题

在开发使用 uni-app 框架的项目时&#xff0c;遇到依赖问题是常见的。本文将介绍如何解决编译过程中出现的 “文件查找失败&#xff1a;‘crypto-js’” 错误&#xff0c;并说明这种错误为什么会发生以及如何避免。 问题背景 在对 uni-app 项目进行编译时&#xff0c;我们可能…...

Apache DolphinScheduler 3.2.2 版本正式发布!

Apache DolphinScheduler 3.2.2 版本正式发布&#xff01; 近日&#xff0c;Apache DolphinScheduler 发布了 3.2.2 版本。此版本主要基于 3.2.1 版本进行了 bug 修复&#xff0c;新增若干特性&#xff0c;并进行了众多改进和 Bug 修复&#xff0c;以及文档修复等。 &#x1…...