DevOps系列文章之 Dockerfile 使用流程

制作项目应用镜像

主要步骤:

Step1、准备项目应用程序包
Step2、编写Dockerfile及启动脚本
Step3、docker build 构建镜像
Step4、docker run 启动容器
Step5、docker exec 进入容器进行验证
Step6、镜像的导入导出
Step7、提交容器生成新镜像

Step1、准备项目应用程序包

根据项目需要,将应用程序包、Nginx配置文件、Mysql初始化sql脚本等文件,保存到/opt/dockermaker/project_app下各文件夹内。

root@bg-244 project_app]# tree /opt/dockermaker/project_app
/opt/dockermaker/project_app
├── bootstrap.sh
├── Dockerfile
├── ibof
│   └── ibof-1.0.0.zip
├── ipy
│   ├── ipy-1.0.0.tar.gz
│   └── ipy_bootstrap.sh
├── isvr
│   ├── isvr-1.0.0.jar
│   └── isvr_bootstrap.sh
├── mysql
│   ├── createDB.sql
│   └── my.cnf
└── nginx_cnf├── https.conf├── nginx.conf├── server.crt└── server.key

Step2、编写Dockerfile及启动脚本

为了缩减镜像尺寸,应尽量注意:

在一个RUN语句中执行多个命令,而不应该写多个RUN语句。
清理无用文件:使用完的安装包,yum缓存等。
下面是代码及说明。

Dockerfile:

# 基础镜像
FROM centos-nmjpy:v1
LABEL maintainer='jason' jasonio_version='1.0.0'# 1、指定工作目录
WORKDIR /opt
COPY bootstrap.sh /opt# 2、复制文件
COPY mysql/my.cnf /opt/mysql/
COPY mysql/createDB.sql /opt/mysql/COPY ibof/ibof-1.0.0.zip /opt
COPY ipy/ipy-1.0.0.tar.gz /opt
COPY ipy/ipy_bootstrap.sh /opt
COPY isvr/isvr-1.0.0.jar /opt
COPY isvr/isvr_bootstrap.sh /optCOPY nginx_cnf/nginx.conf /opt/nginx
COPY nginx_cnf/https.conf /opt/nginx
COPY nginx_cnf/server.key /opt/nginx/security
COPY nginx_cnf/server.crt /opt/nginx/security# 3、准备工作
RUN mkdir -p /data/mysql_conf  \&& mkdir -p /opt/nginx/security  \&& mkdir -p /var/www/ibof  \&& mkdir -p /opt/isvr \&& mkdir -p /opt/ipy  \&& cp -f /opt/mysql/my.cnf /data/mysql_conf/my.cnf  \&& chmod 777 /opt/bootstrap.sh# 4、暴露的容器端口
EXPOSE 22 80 443 3306 8090 8091# 5、容器运行时执行的脚本
ENTRYPOINT ["/opt/bootstrap.sh"]
CMD ["/usr/sbin/init"]

bootstrap.sh:

#!/bin/bash
set -x
echo "#################################### bootstrap.sh start running..."echo "############## init mysql start ..."
INIT_ROOT_PASSWORD="roottmp123"
echo "mysql root temp password 'INIT_ROOT_PASSWORD' : $INIT_ROOT_PASSWORD"# set project mysql root password by input. if input none, then set defult value.
MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-jason123}
echo "project mysql root password 'MYSQL_ROOT_PASSWORD' : $MYSQL_ROOT_PASSWORD"mkdir -p /data/mysql/{data,log,tmp}
chown -R mysql:mysql /data/mysqlecho "[--1--] change mysql config file: /etc/my.cnf -> /data/mysql_conf/my.cnf"
mv /etc/my.cnf /etc/my.cnf.old
ln -s /data/mysql_conf/my.cnf /etc/my.cnfecho "[--2--] mysql new datadir '/data/mysql/data'"
chown -R mysql:mysql /data/mysql
cp -rf /var/lib/mysql/* /data/mysql/data/
chown -R mysql:mysql /data/mysqlecho "[--3--] start mysql ..."
mysqld --user=mysql & 
sleep 2
function start_mysql(){
for p in  {3..0};doPORT=$(ss -anlp|grep 3306|wc -l)if [ $PORT != 1 ]; thenecho "[WARN] MYSQL not run, now start..."mysqld --user=mysql &sleep 2elseecho "[WARN] MYSQL is running"breakfiif [ $p = 0 ]; thenecho >&2 '[ERROR] MYSQL start failed!'exit 1fi
done
}
start_mysql
echo "start_mysql return: $?"echo "[--4--] set new root password ..."
sleep 5
MYSQL_CH="mysql --connect-expired-password -uroot -p$INIT_ROOT_PASSWORD"
$MYSQL_CH << EOF
alter user 'root'@'localhost' identified by '$MYSQL_ROOT_PASSWORD';
grant all on *.* to root@'%' identified by '$MYSQL_ROOT_PASSWORD';
EOF
echo "set new root password return: $?"echo "[--5--] excute init sql ..."
PROJECT_DATABASE_NAME="jason_iodb";
MYSQL="mysql --protocol=socket -uroot -p${MYSQL_ROOT_PASSWORD}"
$MYSQL  -e "use $PROJECT_DATABASE_NAME;" > /dev/null 2>&1
if [ $? != 0 ]; thenecho "creating new database $PROJECT_DATABASE_NAME ..."$MYSQL < /opt/mysql/createDB.sqlecho "creating new database return: $?"
fi
echo "############# init mysql finished."echo ""
echo "############# source /etc/profile"
source /etc/profileecho ""
echo "############## show java version"
java -versionecho ""
echo "############## show pip version"
pip -Vecho ""
echo "############## nginx start by /usr/sbin/nginx"
mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
NGINX_DAEMON=$(cat /opt/nginx/nginx.conf | grep 'daemon off;' | wc -l)
if [ $NGINX_DAEMON != 1 ]; thenecho "daemon off;" >> /opt/nginx/nginx.conf
fi
ln -sf /opt/nginx/nginx.conf /etc/nginx/nginx.conf
ln -sf /opt/nginx/https.conf /etc/nginx/conf.d/https.conf
ln -s /opt/nginx/security /etc/nginx/security
/usr/sbin/nginx &echo "##############################################"
echo "######  下面内容 根据项目需要进行修改  #########"
echo "##############################################"echo ""
echo "############# run ibof"
cd /var/www/ibof
unzip /opt/ibof-1.0.0.zip
mv ibof-1.0.0/* .
bash ibof_inzip_1.sh 
bash ibof_inzip_2.sh 
rm -rf ibof-1.0.0 echo ""
echo "############# run isvr"
mv /opt/isvr-1.0.0.jar /opt/isvr/isvr-1.0.0.jar
mv /opt/isvr_bootstrap.sh /opt/isvr/isvr_bootstrap.sh
cd /opt/isvr
bash isvr_bootstrap.sh
java -jar isvr-1.0.0.jar &echo ""
echo "############# call ipy "
mv /opt/ipy-1.0.0.tar.gz /opt/ipy
mv /opt/ipy_bootstrap.sh /opt/ipy
cd /opt/ipy
tar xzvf ipy-1.0.0.tar.gz
bash ipy_bootstrap.shecho ""
echo "############## bootstrap.sh finished..."
tail -f /dev/null


my.cnf:

[mysqld]
#datadir=/var/lib/mysql
#socket=/var/lib/mysql/mysql.sock
#log-error=/var/log/mysqld.log
#pid-file=/var/run/mysqld/mysqld.pid
symbolic-links=0datadir=/data/mysql/data
log-error=/data/mysql/log/mysqld.err.log
pid-file=/data/mysql/tmp/mysqld.pid   
socket=/data/mysql/tmp/mysqld.sock   
tmpdir=/data/mysql/tmp/lower_case_table_names=1
character-set-server=utf8
max_connections=3000[client]
#socket=/data/mysql/mysql.sock
socket=/data/mysql/tmp/mysqld.sock[mysql]
default-character-set=utf8


createDB.sql:

set names utf8;# set global validate_password.policy=LOW;
# set global validate_password.length=6;
CREATE DATABASE If Not Exists jason_iodb Character Set UTF8;
#CREATE USER 'jason_dba'@'localhost' IDENTIFIED BY 'jason123';
#GRANT all ON jason_iodb.* TO 'jason_dba'@'localhost';
#GRANT all ON jason_iodb.* TO 'root'@'%';use jason_iodb;create table IF NOT EXISTS `tbl_user_images`(
`id` INT UNSIGNED AUTO_INCREMENT,
`user_id` VARCHAR(40) NOT NULL,
`label_name` VARCHAR(255) NOT NULL,
`image` LONGBLOB NOT NULL,
`vector` VARCHAR(4000) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;


代码说明:

1)ENTRYPOINT脚本执行

多个ENTRYPOINT语句存在的时候,只执行最后一个ENTRYPOINT语句。
在构建项目应用镜像时,需要复制环境镜像的booststrap.sh文件,并在此基础上,添加项目应用所需的步骤,比如:

mysql:修改或替换配置文件、指定数据目录datadir、修改root密码、数据库表的初始化、为挂载做准备
nginx:修改或替换配置文件,
项目应用的启动
等等
通常要等环境应用都启动好之后,再启动项目应用。所以Nginx启动命令后要加 & 。

/usr/sbin/nginx &


为了避免ENTRYPOINT脚本执行结束后容器自动停止,所以要在脚本最后添加:

tail -f /dev/null


2)mysql挂载数据目录datadir

容器是临时的,容器一旦删除,容器中的全部内容随之一并删除。
mysql的数据、日志、配置文件,通常都需要持久化到宿主机磁盘,而并不是保留在容器中。

容器中的挂载路径:

配置文件:/data/mysql_conf
数据目录:/data/mysql,其下有data、log、tmp三个子目录。
挂载的思路:

1、启动mysql,生成数据文件,停止mysql(这一步在基础镜像的mysql_init.sh中已完成,数据存放于默认路径/var/lib/mysql/)
2、创建等待挂载的目录,修改所属为mysql:mysql
3、使用新的配置文件/data/mysql_conf/my.cnf,并创建链接,替换原有配置文件/etc/my.cnf
4、修改配置文件,指定数据存放路径datadir=/data/mysql/data(这一步,可以根据项目需要事先修改好,在启动容器时通过挂载,覆盖容器中的配置文件)
5、将原有数据文件复制过去
6、启动mysql
7、容器启动命令中通过-v参数进行挂载

# 2、make mount path
mkdir -p /data/mysql/{data,log,tmp}
chown -R mysql:mysql /data/mysql# 3、change mysql config file: /etc/my.cnf -> /data/mysql_conf/my.cnf
mv /etc/my.cnf /etc/my.cnf.old
ln -s /data/mysql_conf/my.cnf /etc/my.cnf# 5、mysql new datadir '/data/mysql/data'
cp -rf /var/lib/mysql/* /data/mysql/data/# 6、start mysql
mysqld --user=mysql &


容器启动命令挂载示例:

docker run ...  \-v /xxxx/mount/mysql_conf/my.cnf:/data/mysql_conf/my.cnf   \-v /xxxx/mount/mysql/:/data/mysql  \...


3)mysql修改密码

在投入项目使用前,应根据项目需要修改密码。

INIT_ROOT_PASSWORD="roottmp123"
MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-jason123}MYSQL_CH="mysql --connect-expired-password -uroot -p$INIT_ROOT_PASSWORD"
$MYSQL_CH << EOF
alter user 'root'@'localhost' identified by '$MYSQL_ROOT_PASSWORD';
grant all on *.* to root@'%' identified by '$MYSQL_ROOT_PASSWORD';
EOF

$INIT_ROOT_PASSWORD: root临时密码。基础镜像构建过程中,在mysql初始化时设定。值为roottmp123。
$MYSQL_ROOT_PASSWORD: 项目中的root密码。容器启动命令中通过-e参数赋值。默认为jason123。

容器启动命令赋值示例:

docker run ... -e MYSQL_ROOT_PASSWORD=yourpassword123 ...

4)mysql数据库表的初始化

在bootstrap.sh中登录mysql执行初始化脚本createDB.sql:

# 项目DATABASE名称。容器启动命令中通过` -e `参数赋值。默认为`jason_iodb`。
PROJECT_DATABASE_NAME=${PROJECT_DATABASE_NAME:-jason_iodb};
# 设置环境变量
MYSQL="mysql --protocol=socket -uroot -p${MYSQL_ROOT_PASSWORD}"
# 判断 项目DATABASE 是否存在
$MYSQL -e "use $PROJECT_DATABASE_NAME;" > /dev/null 2>&1
# 执行初始化脚本
$MYSQL < /opt/mysql/createDB.sql

在createDB.sql中:
创建一个数据库 jason_iodb,新建一个表tbl_user_images:

# 创建一个 DATABASE ,命名为 jason_iodb 
CREATE DATABASE If Not Exists jason_iodb Character Set UTF8;
use jason_iodb;
create table IF NOT EXISTS `tbl_user_images`(
)

5)Nginx配置文件替换及启动(根据项目需要进行修改)
在Dockerfile中,复制Nginx的配置文件。

COPY nginx_cnf/nginx.conf /opt/nginx
COPY nginx_cnf/https.conf /opt/nginx
COPY nginx_cnf/server.key /opt/nginx/security
COPY nginx_cnf/server.crt /opt/nginx/security

在bootstrap.sh中,替换Nginx的配置文件,并启动。

mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
NGINX_DAEMON=$(cat /opt/nginx/nginx.conf | grep 'daemon off;' | wc -l)
if [ $NGINX_DAEMON != 1 ]; thenecho "daemon off;" >> /opt/nginx/nginx.conf
fi
ln -sf /opt/nginx/nginx.conf /etc/nginx/nginx.conf
ln -sf /opt/nginx/https.conf /etc/nginx/conf.d/https.conf
ln -s /opt/nginx/security /etc/nginx/security/usr/sbin/nginx &

如果想使用项目自己的Nginx配置,可以在启动命令里通过-v参数进行挂载:

docker run ...   \-v /xxxx/mount/nginx/nginx.conf:/opt/nginx/nginx.conf  \-v /xxxx/mount/nginx/https.conf:/opt/nginx/https.conf  \-v /xxxx/mount/nginx/security/server.key:/opt/nginx/security/server.key  \-v /xxxx/mount/nginx/security/server.crt:/opt/nginx/security/server.crt  \
...

6)项目应用的复制、解压、启动(根据项目需要进行修改)

Dockerfile:

COPY ibof/ibof-1.0.0.zip /opt
COPY ipy/ipy-1.0.0.tar.gz /opt
COPY ipy/ipy_bootstrap.sh /opt
COPY isvr/isvr-1.0.0.jar /opt
COPY isvr/isvr_bootstrap.sh /opt
RUN mkdir -p /var/www/ibof  \&& mkdir -p /opt/isvr \&& mkdir -p /opt/ipy

bootstrap.sh:

echo "############# run ibof"
cd /var/www/ibof
unzip /opt/ibof-1.0.0.zip
mv ibof-1.0.0/* .
bash ibof_inzip_1.sh 
bash ibof_inzip_2.sh 
rm -rf ibof-1.0.0 echo ""
echo "############# run isvr"
mv /opt/isvr-1.0.0.jar /opt/isvr/isvr-1.0.0.jar
mv /opt/isvr_bootstrap.sh /opt/isvr/isvr_bootstrap.sh
cd /opt/isvr
bash isvr_bootstrap.sh
java -jar isvr-1.0.0.jar &echo ""
echo "############# call ipy "
mv /opt/ipy-1.0.0.tar.gz /opt/ipy
mv /opt/ipy_bootstrap.sh /opt/ipy
cd /opt/ipy
tar xzvf ipy-1.0.0.tar.gz
bash ipy_bootstrap.sh

Step3、docker build 构建镜像
构建镜像:
假设项目名为 io ,所以将镜像命名为centos-io,版本号v1。
若不写版本号,则默认为latest。

# 进入 Dockerfile 文件所在路径
cd /opt/dockermaker/project_app
# build --- 创建镜像的命令
# -t --- 指定target 名称
# centos-io:v1 --- 镜像名称:镜像tag
# . --- 执行当前路径下的 Dockerfile 文件
docker build -t centos-io:v1 .


查看镜像:

docker image lsREPOSITORY      TAG       IMAGE ID       CREATED        SIZE
centos-io       v1        c54f86a7261a   3 hours ago    6.23GB
centos-nmjpy    v1        4bdd37c68d92   2 hours ago    6.14GB
centos          centos7   5e35e350aded   3 months ago   203MB

删除镜像:

# docker image rm <镜像名:tag 或 镜像ID>
docker image rm centos-io:v1
docker image rm c54f86a7261a

Step4、docker run 启动容器
4.1、启动容器(不挂载)

docker run -v /tmp/:/tmp   \-itd --privileged --cap-add=SYS_ADMIN  \-p 50022:22    \-p 50080:80    \-p 50443:443   \-p 53306:3306  \-p 58090:8090  \-p 58091:8091  \-e MYSQL_ROOT_PASSWORD=yourpassword123  \--name=centos-io:v1 \centos-io  \/usr/sbin/init

-v /tmp/:/tmp :挂载宿主机的一个目录,格式:宿主机目录:容器目录。
-it : 启动互动模式。
-d : 后台运行。
--privileged : 指定容器是否是特权容器。在docker容器运行时,让系统拥有真正的root权限。
--cap-add SYS_ADMIN : 添加系统的权限,不然系统很多功能都用不了的。
-p 53306:3306 :端口映射,格式:宿主机端口:容器端口。
-e : 环境变量赋值。格式:变量名=变量值。
--name=centos-io :将容器命名为centos-io。
centos-io:v1 :指定镜像,格式:镜像名称:镜像tag
/usr/sbin/init :初始容器里的CENTOS,用于启动dbus-daemon。

4.2、启动容器(挂载)
准备:

1、创建目录。
2、将编辑好的Mysql、Nginx配置文件放置于各自对应的目录下(参考下面的文件结构)。
3、创建容器之前一定要清空mount/mysql下data、log、tmp目录。

cd /opt/dockermaker/mount
mkdir -p /opt/dockermaker/mount/nginx/security
mkdir -p /opt/dockermaker/mount/mysql_conf
mkdir -p /opt/dockermaker/mount/mysql/{data,log,tmp}
rm -rf /opt/dockermaker/mount/mysql/{data,log,tmp}/*

文件结构:

root@bg-244 ~]# tree /opt/dockermaker/mount
/opt/dockermaker/mount├── mysql│   ├── data│   ├── log│   └── tmp├── mysql_conf│   └── createDB.sql│   └── mysql.mount.cnf└── nginx├── https.conf├── nginx.conf└── security├── server.crt└── server.key

createDB.sql:
挂载的createDB.sql,会创建一个数据库jason_iodb_mount,并创建一张表tbl_user_images_mount。

启动容器 & 挂载:

docker run -v /tmp/:/tmp   \-v /opt/dockermaker/mount/mysql_conf/mysql.mount.cnf:/data/mysql_conf/my.cnf \-v /opt/dockermaker/mount/mysql_conf/createDB.sql:/opt/mysql/createDB.sql    \-v /opt/dockermaker/mount/mysql/:/data/mysql  \-v /opt/dockermaker/mount/nginx/nginx.conf:/opt/nginx/nginx.conf  \-v /opt/dockermaker/mount/nginx/https.conf:/opt/nginx/https.conf  \-v /opt/dockermaker/mount/nginx/security/server.key:/opt/nginx/security/server.key  \-v /opt/dockermaker/mount/nginx/security/server.crt:/opt/nginx/security/server.crt  \-itd --privileged --cap-add=SYS_ADMIN  \-p 50022:22    \-p 50080:80    \-p 50443:443   \-p 53306:3306  \-p 58090:8090  \-p 58091:8091  \-e MYSQL_ROOT_PASSWORD=yourpassword123  \-e PROJECT_DATABASE_NAME=jason_iodb--name=centos-io:v1 \centos-io  \/usr/sbin/init


Step5、docker exec 进入容器进行验证
进入容器:

docker exec -it centos-io bash

退出容器(不停止容器):

Ctrl+P+Q 同时按下

Step6、镜像的导入导出
镜像导出:
镜像导出,保存到指定的本地文件

docker save centos-io:v1 -o /opt/docker-image-centos-io-v1.tar

centos-io:v1 :指定需要导出的镜像,格式:镜像名称:镜像tag
-o /path/file.tar :指定本地文件
镜像导入:
镜像导入,不用指定镜像名称。

docker load -i /home/src/docker-image-nginx-1.13.tar

-i /path/file.tar :指定本地文件
当出现如下提示时,即表示成功:

Loaded image: xxxx:xxx

Step7、提交容器生成新镜像
进入容器后可以操作容器,操作容器会把容器置位新状态。
停止再启动后,容器会保持新状态,但是镜像没有变化,这个新状态仍然是临时的。
但是基于相同的镜像再创建一个容器,新容器将会是原始状态。

所以修改容器后,可以将容器的新状态提交(commit)成一个新的镜像。
主要步骤:
启动容器==>进入容器==>修改容器==>退出容器==>停止容器==>提交容器,获得新镜像。

修改容器:

如同操作Linux一样。

容器与宿主机之间的文件操作:

容器 ==> 宿主机 ,将容器下/root/test.js复制到宿主机/opt

docker cp <容器名>:/root/test.js /opt

宿主机 ==> 容器,将宿主机/opt/test.js复制到容器下/root

docker cp /opt/test.js <容器名>:/root

退出容器(不停止容器):

Ctrl+P+Q 同时按下

提交容器:

docker commit <容器id> centos-io:v2

centos-io:v2:新镜像,格式:镜像名称:镜像tag

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

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

相关文章

如何缩短 js 解析时间,如何优化首屏(延迟加载)

缩短js解析时间 代码优化 避免全局查找&#xff08;沿着作用域链找需要时间&#xff09;&#xff0c;避免闭包&#xff0c;用数据结构等 减小js的大小&#xff1a;压缩和混淆 压缩 剔除没用到的代码&#xff0c;把长表达式转换成同含义的短表达式等 语法转换和优化&#…

c++ 无锁队列的简单实现

无锁队列的基本介绍 一个关于无锁队列的多线程读写代码示例。在这里&#xff0c;我提供一个简单的示例来说明这个问题。 在使用无锁队列时&#xff0c;需要注意以下几点&#xff1a; 使用原子操作来实现对队列的读写操作&#xff0c;以避免多线程同时访问同一数据导致的竞争条…

在SPringBoot生成验证码

1.引入依赖,这个依赖中包含了生成验证码的工具类 <!--引入hutool --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.3.9</version></dependency> 2.编写配置类 import cn.hu…

Linux字符设备操作函数

Linux字符设备操作函数是指对字符设备进行打开、关闭、读取、写入、控制等基本操作的函数&#xff0c;它们通过字符设备结构体中的 file_operations 结构体来定义。常用的字符设备操作函数包括&#xff1a; 1、open: 当一个进程试图打开设备文件时&#xff0c;调用这个函数。开…

华润燃气牵手腾讯云 数字技术助力燃气行业高质量发展

7月13日&#xff0c;华润燃气与腾讯云正式签署战略合作协议。双方将充分发挥各自优势&#xff0c;探索AI大模型在燃气行业的深度应用&#xff0c;并深耕分布式计算、连接和客户运营等领域&#xff0c;不断提升燃气民生服务的效率、质量&#xff0c;共同推动行业数字化转型和高质…

ASEMI快恢复二极管MUR20100CTR在电子工程中的应用

编辑-Z 随着电子技术的日益发展&#xff0c;各种电子元件的使用场景与需求也在逐步扩大。今天&#xff0c;我们将聚焦于一款广泛应用于各类电路的二极管——MUR20100CTR&#xff0c;来详细解读其性能特征及应用。 一、MUR20100CTR二极管的主要特性 MUR20100CTR是一款极高性能的…

DataTable数据对比

DataTable数据对比 文章目录 DataTable数据对比前言一、计算DataTable差集结构不同的情况结构相同的情况 二、计算DataTable交集结构不同的情况结构相同的情况 三、计算DataTable的并集合两个DaTable结构相同的情况计算并集 前言 开发中我们经常会出现查询数据库后返回DataTab…

【iOS安全】iphone出现support.apple.com/iphone/restore

解决iphone出现support.apple.com/iphone/restore 解决方法1&#xff1a;使用爱思助手 可能是因为手机进入了恢复模式 手机连接Mac端的爱思助手之后&#xff0c;使用爱思助手的“退出恢复模式” 经测试有效 解决方法2&#xff1a;iphone强制重启 强制重新启动iPhone8或iPhone…

[Java]Set、Map、List常见实现类的特点、使用方法总结

文章目录 1、图谱2、List1、ArrayList1. 特点2. 常见方法 2、LinkedList1、特点2、常见方法 3、Vector1、特点 3、Map1、HashMap1、特点常用方法 2、TreeMap1、特点 3、LinkedHashMap1、特点 4、Set1、HashSet1 、特点2、常用方法 2、LinkedHashSet特点 3、TreeSet1、特点2、使…

Python - Django 框架 - 设置SECRET_KEY

在Django中&#xff0c;SECRET_KEY是一个重要的配置项&#xff0c;用于加密和保护用户数据、会话和其他敏感信息。下面是设置SECRET_KEY的几种常见方法&#xff1a; 1、在settings.py文件中硬编码设置&#xff1a; 打开项目中的settings.py文件&#xff0c;并在其中定义一个字…

SEED实验复现

SEED 项目由雪城大学教授杜文亮于 2002 年启动雪城大学。它由美国总共1万美元资助 美国国家科学基金会。现在&#xff0c;SEED 实验室正在被超过 全球数千个研究所。SEED 代表 &#xff08;SEcurity EDucaton&#xff09;。 https://github.com/seed-labs/seed-labs 该项目使用…

C++牛客WebServer项目学习笔记一

1.Linux系统命令&#xff1a; sudo apt install softname # sudo 管理员权限&#xff1b;apt 安装软件命令&#xff1b;ps -ef | grep ssh # ps 查看进程命令&#xff1b;| 管道符&#xff1b;grep 过滤出&#xff08;过滤出ssh关键词&#xff09;&#xff1b; 3.Ctrl滚动鼠标…

Qt添加第三方字体

最近开发项目时&#xff0c;据说不能用系统自带的微软雅黑字体&#xff0c;于是找一个开源的字体&#xff0c;思源黑体&#xff0c;这个是google和Adobe公司合力开发的可以免费使用。本篇记录一下Qt使用第三方字体的方式。字体从下载之家下载http://www.downza.cn/soft/266042.…

Python爬虫——urllib_微博cookie登陆

cookie登陆适用场景&#xff1a; 适用场景&#xff1a;数据采集的时候&#xff0c;需要绕过登陆&#xff0c;然后进入到某个页面 # 适用场景&#xff1a;数据采集的时候&#xff0c;需要绕过登陆&#xff0c;然后进入到某个页面 import urllib.requesturl https://weibo.cn/7…

selenium

现场打脸&#xff1a;如何使用Selenium批量上传文件&#xff1f; Automa官网 低代码开发&#xff0c;推荐一款Web 端自动化神器&#xff1a;Automa 网页自动化操作工具Automa学习使用记录01 网页自动化操作工具Automa学习使用记录02 - 变量用法 selenium 完整的线程和进程创建…

【解决】Android Studio打包出现not found for signing config ‘externalOverride‘

问题出现场景 之前我的这个项目在另一台电脑上开发&#xff0c;现在迁移到这台计算机上&#xff0c;出现了key报错的问题&#xff0c;网络上有些说需要在XML中进行配置signature相关的内容&#xff0c;这个感觉比较复杂&#xff0c;本文主要介绍一个简单的解决方法&#xff0c;…

SOT封装特点和优势,sot23封装尺寸

SOT封装是一种常用的集成电路封装类型&#xff0c;常见的SOT封装类型包括3引脚&#xff08;如SOT-23&#xff09;、4引脚&#xff08;如SOT-89和SOT-223&#xff09;和6引脚&#xff08;如SOT-363&#xff09;&#xff0c;可以适应不同的电路设计和功能要求。具有以下特点和优势…

机械设计制造及其自动化专业向PLC方向发展的可行性

是的&#xff0c;机械设计制造及其自动化专业往PLC&#xff08;可编程逻辑控制器&#xff09;方向发展是可行的。PLC是一种用于控制和自动化各种机械设备和工业过程的计算机控制系统。它被广泛应用于工业自动化领域&#xff0c;包括制造业、能源行业、交通运输等。 我这里刚好…

UNIX/LINUX fork函数的问题 并不适合共享

起因介绍 一位朋友问我一个关于socket通信的相关问题&#xff0c;其需要解决的问题如下&#xff1a; 需要存在一个服务器进程&#xff0c;服务器进程会进行监听&#xff0c;负责建立与客户端的socket连接&#xff0c;同时可以存在多个客户端进程&#xff0c;客户端进程之间可以…

提示工程师:如何写好Prompt

提示工程由来 提示工程是一门相对较新的学科&#xff0c;用于开发和优化提示以有效地将语言模型 (LM) 用于各种应用程序和研究主题。 研究人员使用提示工程来提高 LLM 在广泛的常见和复杂任务&#xff08;例如问题回答和算术推理&#xff09;上的能力。 开发人员使用提示工程…