Nginx官方镜像Dockerfile浅析

目录

Dockerfile获取

dfimage逆向获取

Nginx官网获取

Dockerfile分析

启动命令分析

Docker 容器入口点脚本分析

exec "$@"

exec 命令

"$@" 参数

总结


        在云原生技术快速发展的今天,Docker 作为容器技术的代表,为软件的打包、分发和部署提供了一种轻量级、可移植的解决方案。Dockerfile 作为 Docker 的核心组件之一,其设计和编写直接关系到容器镜像的构建效率和运行时的性能。了解和掌握 Dockerfile 的关键技术点,对于任何希望在云原生领域内进行开发和运维的工程师来说都是至关重要的。

        本文旨在通过分析 Nginx 官方 Docker 镜像的 Dockerfile,探讨 Dockerfile 的获取方法、结构和编写策略,以及容器启动脚本的作用和设计原则。我们将深入讨论在 Dockerfile 中使用 exec "$@" 的好处,以及这种做法在其他镜像设计中的应用价值,为构建更加高效、可靠的容器化应用打下坚实的基础。

Dockerfile获取

dfimage逆向获取

alias dfimage='docker run -v /var/run/docker.sock:/var/run/docker.sock --rm alpine/dfimage'/usr/bin/dockerdfimage nginx:1.25.4

dfimage='docker run -v /var/run/docker.sock:/var/run/docker.sock --rm alpine/dfimage'/usr/bin/docker nginx:1.25.4

逆向Dockerfile

CMD ["bash"]
LABEL maintainer=NGINX Docker Maintainers <docker-maint@nginx.com>
ENV NGINX_VERSION=1.25.4
ENV NJS_VERSION=0.8.3
ENV PKG_RELEASE=1~bookworm
RUN RUN set -x  \&& groupadd --system --gid 101 nginx  \&& useradd --system --gid nginx --no-create-home --home /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx  \&& apt-get update  \&& apt-get install --no-install-recommends --no-install-suggests -y gnupg1 ca-certificates  \&& NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62; NGINX_GPGKEY_PATH=/usr/share/keyrings/nginx-archive-keyring.gpg; export GNUPGHOME="$(mktemp -d)"; found=''; for server in hkp://keyserver.ubuntu.com:80 pgp.mit.edu ; do echo "Fetching GPG key $NGINX_GPGKEY from $server"; gpg1 --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY"  \&& found=yes  \&& break; done; test -z "$found"  \&& echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY"  \&& exit 1; gpg1 --export "$NGINX_GPGKEY" > "$NGINX_GPGKEY_PATH" ; rm -rf "$GNUPGHOME"; apt-get remove --purge --auto-remove -y gnupg1  \&& rm -rf /var/lib/apt/lists/*  \&& dpkgArch="$(dpkg --print-architecture)"  \&& nginxPackages=" nginx=${NGINX_VERSION}-${PKG_RELEASE} nginx-module-xslt=${NGINX_VERSION}-${PKG_RELEASE} nginx-module-geoip=${NGINX_VERSION}-${PKG_RELEASE} nginx-module-image-filter=${NGINX_VERSION}-${PKG_RELEASE} nginx-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${PKG_RELEASE} "  \&& case "$dpkgArch" in amd64|arm64) echo "deb [signed-by=$NGINX_GPGKEY_PATH] https://nginx.org/packages/mainline/debian/ bookworm nginx" >> /etc/apt/sources.list.d/nginx.list  \&& apt-get update ;; *) echo "deb-src [signed-by=$NGINX_GPGKEY_PATH] https://nginx.org/packages/mainline/debian/ bookworm nginx" >> /etc/apt/sources.list.d/nginx.list  \&& tempDir="$(mktemp -d)"  \&& chmod 777 "$tempDir"  \&& savedAptMark="$(apt-mark showmanual)"  \&& apt-get update  \&& apt-get build-dep -y $nginxPackages  \&& ( cd "$tempDir"  \&& DEB_BUILD_OPTIONS="nocheck parallel=$(nproc)" apt-get source --compile $nginxPackages )  \&& apt-mark showmanual | xargs apt-mark auto > /dev/null  \&& { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; }  \&& ls -lAFh "$tempDir"  \&& ( cd "$tempDir"  \&& dpkg-scanpackages . > Packages )  \&& grep '^Package: ' "$tempDir/Packages"  \&& echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list  \&& apt-get -o Acquire::GzipIndexes=false update ;; esac  \&& apt-get install --no-install-recommends --no-install-suggests -y $nginxPackages gettext-base curl  \&& apt-get remove --purge --auto-remove -y  \&& rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list  \&& if [ -n "$tempDir" ]; then apt-get purge -y --auto-remove  \&& rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; fi  \&& ln -sf /dev/stdout /var/log/nginx/access.log  \&& ln -sf /dev/stderr /var/log/nginx/error.log  \&& mkdir /docker-entrypoint.d # buildkit
COPY docker-entrypoint.sh / # buildkitdocker-entrypoint.shCOPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d # buildkitdocker-entrypoint.d/docker-entrypoint.d/10-listen-on-ipv6-by-default.shCOPY 15-local-resolvers.envsh /docker-entrypoint.d # buildkitdocker-entrypoint.d/docker-entrypoint.d/15-local-resolvers.envshCOPY 20-envsubst-on-templates.sh /docker-entrypoint.d # buildkitdocker-entrypoint.d/docker-entrypoint.d/20-envsubst-on-templates.shCOPY 30-tune-worker-processes.sh /docker-entrypoint.d # buildkitdocker-entrypoint.d/docker-entrypoint.d/30-tune-worker-processes.shENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE map[80/tcp:{}]
STOPSIGNAL SIGQUIT
CMD ["nginx" "-g" "daemon off;"]

Nginx官网获取

docker-nginx/mainline/debian/Dockerfile at 1f227619c1f1baa0bed8bed844ea614437ff14fb · nginxinc/docker-nginx · GitHub

官网Dockerfile

#
# NOTE: THIS DOCKERFILE IS GENERATED VIA "update.sh"
#
# PLEASE DO NOT EDIT IT DIRECTLY.
#
FROM debian:bookworm-slimLABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"ENV NGINX_VERSION   1.25.4
ENV NJS_VERSION     0.8.3
ENV PKG_RELEASE     1~bookwormRUN set -x \
# create nginx user/group first, to be consistent throughout docker variants&& groupadd --system --gid 101 nginx \&& useradd --system --gid nginx --no-create-home --home /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \&& apt-get update \&& apt-get install --no-install-recommends --no-install-suggests -y gnupg1 ca-certificates \&& \NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62; \NGINX_GPGKEY_PATH=/usr/share/keyrings/nginx-archive-keyring.gpg; \export GNUPGHOME="$(mktemp -d)"; \found=''; \for server in \hkp://keyserver.ubuntu.com:80 \pgp.mit.edu \; do \echo "Fetching GPG key $NGINX_GPGKEY from $server"; \gpg1 --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY" && found=yes && break; \done; \test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY" && exit 1; \gpg1 --export "$NGINX_GPGKEY" > "$NGINX_GPGKEY_PATH" ; \rm -rf "$GNUPGHOME"; \apt-get remove --purge --auto-remove -y gnupg1 && rm -rf /var/lib/apt/lists/* \&& dpkgArch="$(dpkg --print-architecture)" \&& nginxPackages=" \nginx=${NGINX_VERSION}-${PKG_RELEASE} \nginx-module-xslt=${NGINX_VERSION}-${PKG_RELEASE} \nginx-module-geoip=${NGINX_VERSION}-${PKG_RELEASE} \nginx-module-image-filter=${NGINX_VERSION}-${PKG_RELEASE} \nginx-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${PKG_RELEASE} \" \&& case "$dpkgArch" in \amd64|arm64) \
# arches officialy built by upstreamecho "deb [signed-by=$NGINX_GPGKEY_PATH] https://nginx.org/packages/mainline/debian/ bookworm nginx" >> /etc/apt/sources.list.d/nginx.list \&& apt-get update \;; \*) \
# we're on an architecture upstream doesn't officially build for
# let's build binaries from the published source packagesecho "deb-src [signed-by=$NGINX_GPGKEY_PATH] https://nginx.org/packages/mainline/debian/ bookworm nginx" >> /etc/apt/sources.list.d/nginx.list \\
# new directory for storing sources and .deb files&& tempDir="$(mktemp -d)" \&& chmod 777 "$tempDir" \
# (777 to ensure APT's "_apt" user can access it too)\
# save list of currently-installed packages so build dependencies can be cleanly removed later&& savedAptMark="$(apt-mark showmanual)" \\
# build .deb files from upstream's source packages (which are verified by apt-get)&& apt-get update \&& apt-get build-dep -y $nginxPackages \&& ( \cd "$tempDir" \&& DEB_BUILD_OPTIONS="nocheck parallel=$(nproc)" \apt-get source --compile $nginxPackages \) \
# we don't remove APT lists here because they get re-downloaded and removed later\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
# (which is done after we install the built packages so we don't have to redownload any overlapping dependencies)&& apt-mark showmanual | xargs apt-mark auto > /dev/null \&& { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; } \\
# create a temporary local APT repo to install from (so that dependency resolution can be handled by APT, as it should be)&& ls -lAFh "$tempDir" \&& ( cd "$tempDir" && dpkg-scanpackages . > Packages ) \&& grep '^Package: ' "$tempDir/Packages" \&& echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list \
# work around the following APT issue by using "Acquire::GzipIndexes=false" (overriding "/etc/apt/apt.conf.d/docker-gzip-indexes")
#   Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied)
#   ...
#   E: Failed to fetch store:/var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages  Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied)&& apt-get -o Acquire::GzipIndexes=false update \;; \esac \\&& apt-get install --no-install-recommends --no-install-suggests -y \$nginxPackages \gettext-base \curl \&& apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list \\
# if we have leftovers from building, let's purge them (including extra, unnecessary build deps)&& if [ -n "$tempDir" ]; then \apt-get purge -y --auto-remove \&& rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \fi \
# forward request and error logs to docker log collector&& ln -sf /dev/stdout /var/log/nginx/access.log \&& ln -sf /dev/stderr /var/log/nginx/error.log \
# create a docker-entrypoint.d directory&& mkdir /docker-entrypoint.dCOPY docker-entrypoint.sh /
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d
COPY 15-local-resolvers.envsh /docker-entrypoint.d
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d
COPY 30-tune-worker-processes.sh /docker-entrypoint.d
ENTRYPOINT ["/docker-entrypoint.sh"]EXPOSE 80STOPSIGNAL SIGQUITCMD ["nginx", "-g", "daemon off;"]

Dockerfile分析

启动命令分析

ENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE map[80/tcp:{}]
STOPSIGNAL SIGQUIT
CMD ["nginx" "-g" "daemon off;"]
  • ENTRYPOINT 设置了容器启动时执行的主命令,即执行 /docker-entrypoint.sh 脚本。

  • CMD 提供了额外的参数,这些参数将传递给 /docker-entrypoint.sh。

这意味着当容器启动时,实际执行的命令会是 /docker-entrypoint.sh nginx -g "daemon off;"。这里,nginx -g "daemon off;" 是作为参数传递给 /docker-entrypoint.sh 脚本的。

Docker 容器入口点脚本分析

docker-entrypoint.sh

#!/bin/sh
# vim:sw=4:ts=4:etset -e  # 如果任何语句的执行结果不是true则立即退出脚本# 定义一个用于输出日志的函数
entrypoint_log() {# 如果环境变量NGINX_ENTRYPOINT_QUIET_LOGS未设置或为空,打印日志信息if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; thenecho "$@"fi
}# 检查传递给脚本的第一个参数是否是nginx或nginx-debug
if [ "$1" = "nginx" ] || [ "$1" = "nginx-debug" ]; then# 查找/docker-entrypoint.d/目录下是否有文件存在if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; thenentrypoint_log "$0: /docker-entrypoint.d/ 目录不为空,尝试进行配置"entrypoint_log "$0: 在 /docker-entrypoint.d/ 目录中查找shell脚本"# 遍历目录下所有文件,并按版本号排序find "/docker-entrypoint.d/" -follow -type f -print | sort -V | while read -r f; docase "$f" in*.envsh)# 如果文件具有执行权限,使用source命令执行它if [ -x "$f" ]; thenentrypoint_log "$0: 正在加载 $f";. "$f"else# 如果文件没有执行权限,打印警告日志entrypoint_log "$0: 忽略 $f,没有执行权限";fi;;*.sh)# 如果文件具有执行权限,直接执行它if [ -x "$f" ]; thenentrypoint_log "$0: 正在执行 $f";"$f"else# 如果文件没有执行权限,打印警告日志entrypoint_log "$0: 忽略 $f,没有执行权限";fi;;# 忽略其他类型的文件*) entrypoint_log "$0: 忽略 $f";;esacdoneentrypoint_log "$0: 配置完成;准备启动"elseentrypoint_log "$0: 在 /docker-entrypoint.d/ 目录中未找到文件,跳过配置"fi
fi# 使用传递给脚本的参数替换当前进程,通常用于启动主程序
exec "$@"

exec "$@"

        exec "$@"是上面docker-entrypoint.sh脚本的最后一行,这行命令是 Docker 容器入口点脚本的核心部分,它负责执行容器启动时用户指定的命令。

exec 命令

  • exec 用于执行命令并用该命令替换当前的 shell 进程。这意味着 exec 后面的命令将接管当前的进程,并且当 exec 执行的命令结束时,进程也会结束。

  • 使用 exec 执行命令的好处是,它不会启动新的进程,而是直接在当前进程中运行命令。在 Docker 容器的环境中,这意味着执行的命令(如 nginx)将成为容器进程的主进程。这对于 Docker 容器的生命周期管理非常重要。

"$@" 参数

  • "$@" 是一个特殊的 shell 参数,代表传递给脚本的所有命令行参数的列表,且每个参数都作为独立的引用字符串处理。

  • 在 Docker 容器的上下文中,当运行一个容器并传递命令行参数时,这些参数会被传递给容器的入口点脚本。"$@" 就是用来接收这些参数的。

  • 例如,如果运行 docker run [image] nginx -g "daemon off;",那么 nginx -g "daemon off;" 就是传递给入口点脚本的参数,"$@" 就会包含这些参数。

       

总结

        综上所述,exec "$@" 这行命令的作用是执行传递给入口点脚本的命令(如 nginx -g "daemon off;"),并且以这个命令为容器的主进程。这保证了容器直接运行指定服务,如 Nginx,并且当该服务停止时,容器也会停止。

        在设计其他镜像时,尤其是需要处理信号或需要确保容器优雅停止的场景中,使用 exec "$@" 可以提供类似的优势。例如,数据库镜像、Web 服务器镜像或任何长期运行的服务都可以从这种模式中受益。它确保了容器能够接收到停止信号并优雅地终止,同时也避免了资源泄漏的问题。

        总的来说,使用 exec "$@" 是一种常见的最佳实践,可以提高容器的运行效率和可靠性。在设计容器镜像时,尤其是当容器需要优雅地处理停止和重启信号时,应该考虑采用这种模式。

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

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

相关文章

RHCE:请给openlab搭建web

1.关闭所有安全软件已经防火墙 2.安装所需软件 3.在Windows 文件中进行DNS映射 C:\Windows\System32\drivers\etc\hosts 文件进 行DNS 映射 4.创建www.openlab.com网站 5.创建教学资料子网站 6.创建学生信息子网站 进行验证 7.创建缴费子网站

Advisor 被重复代理问题排查

问题场景 项目中存在多个 AbstractAdvisorAutoProxyCreator 且其持有的 Advisor Bean 重复 问题复现 相关代码 ResponseBodyRequiresPermissions(PermissionConstant.****)GetMapping(value "/query****.json", name "")public List<***> query…

HCIP(GRE MGRE)DSVPN等综合实验

要求&#xff1a; 1、r5为isp&#xff0c;只能进行ip地址的配置&#xff0c;其所有ip地址均为共有ip地址 2、r1和r5使用ppp的PAP认证&#xff0c;r5为主认证方 r2和r5之间使用ppp的chap认证&#xff0c;r5为主认证方 r3和r5之间使用HDLC封装 3、r1 r2 r3构建一个MGRE环境…

Ruoyi-Cloud-Plus_使用Docker部署分布式微服务系统---SpringCloud工作笔记200

1.首先安装docker: 如果以前安装过首先执行: yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine 去卸载docker 2.安装dokcer需要的工具包…

【CASS精品教程】CASS添加标准图幅(50×50cm+50×40cm)

大比例尺地形图图幅一般分为正方形和矩形分幅两种,本文讲解CASS中添加标准图幅(5050cm、5040cm)的方法。 文章目录 一、CASS参数配置二、添加标准图幅(5050cm)三、添加标准图幅(5040cm)打开基于CASS自带案例数据study.dat绘制好的地形图study.dwg,如下图所示,下面来演示两种…

Numpy 初体验

文章目录 第1关&#xff1a;Numpy 创建数组第2关&#xff1a;Numpy 数组的基本运算第3关&#xff1a;Numpy 数组的切片与索引第4关&#xff1a;Numpy 数组的堆叠第5关&#xff1a;Numpy 的拆分 第1关&#xff1a;Numpy 创建数组 编程要求 本关的任务是&#xff0c;补全右侧编辑…

MySQL的主从复制和读写分离

目录 一、MySQL的主从复制 1、MySQL主从复制的原理 1.1 MySQL的复制类型 1.2 MySQL主从复制的工作过程 1.3 MySQL主从复制延迟 1.3.1 原因 1.3.2 解决方案 2、搭建MySQL的主从复制 实验环境 实验前提 ①Mysql主从服务器时间同步 ②主服务器的mysql配置 ③从服务器的…

Linux下javaweb项目部署

javaweb项目部署测试 测试环境&#xff1a;centos7 下载安装jdk rpm -ivh jdk-8u131-linux-x64.rpm 下载安装MySQL wget https://downloads.mysql.com/archives/get/p/23/file/mysql-community-server-5.7.33-1.el7.x86_64.rpm https://downloads.mysql.com/archives/get/p…

AI预测福彩3D第19弹【2024年3月27日预测--第5套算法开始计算第1次测试】

今天早上&#xff0c;突然做了一个大胆的决定&#xff0c;直接用新的算法来搞4码定位&#xff0c;新的算法融合了冷温热的趋势分析&#xff0c;让我自己搭建的AI深度学习模型来预测相关号码的冷温热走势&#xff0c;并赋予相关权重&#xff0c;然后通过权重来进行打分排名。当然…

9.HelloWorld案例常见问题

文章目录 一、BUG二、BUG的解决三、HelloWorld常见问题 一、BUG BUG&#xff08;小甲虫&#xff09;。计算机刚开始出现的时候&#xff0c;因为体积比较大&#xff0c;一些小虫子很容易转进去。有一天有一只蟑螂钻到了计算机当中&#xff0c;从而导致计算机不能正常运行&#…

vue3服务端渲染警告解决----DefinePlugin

Bundler 构建功能标志 有关 vuejs.org 的详细参考 esm-bundlerVue 的构建公开了可以在编译时覆盖的全局特性标志&#xff1a; __VUE_OPTIONS_API__ 违约&#xff1a;true启用/禁用选项 API 支持 __VUE_PROD_DEVTOOLS__ 违约&#xff1a;false在生产环境中启用/禁用 devtools 支…

2024/3/27打卡更小的数(十四届蓝桥杯)——区间DP

目录 题目 思路 代码 题目 思路 题目说求数组某个区间中的数进行翻转&#xff0c;由于区间选择多&#xff0c;首先想到DP问题。 第一版想到的方法&#xff08;错误的&#xff09;&#xff0c;当进行状态计算的时候&#xff0c;无法判定区间是否翻转后满足要求&#xff0c;…

c++|string模拟实现

目录 一、string.h 二、string.cpp 三、Test.cpp 对string的各种接口进行一个简易版的模拟实现&#xff0c;在模拟实现完之后对string的底层实现有了进一步的理解&#xff0c;了解大佬的编程写法思路。也算是对string有了一个小总结。 一、string.h 接口的声明。放在.h文件中…

MySQL安装和配置(超详细)

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;&#x1f468;&#x1f3fb;‍&#x1f393;告别&#xff0c;今天 &#x1f4d4;高质量专栏 &#xff1a;☕java趣味之旅 欢迎&#x1f64f;点赞&#x1f5e3;️评论&#x1f4e5;收藏&#x1f493;关注 &#x1f496;衷心的希…

武汉星起航公司助力零经验新手卖家征战亚马逊跨境电商市场

在数字化浪潮的推动下&#xff0c;亚马逊跨境电商行业正逐渐成为众多创业者和企业家们的新战场。然而&#xff0c;对于零经验的新手卖家而言&#xff0c;这片广袤的电商海洋无疑充满了未知与挑战。在这个关键时刻&#xff0c;武汉星起航公司以其专业的服务和深厚的行业积累&…

day 36 贪心算法 part05● 435. 无重叠区间 ● 763.划分字母区间 ● 56. 合并区间

一遍过。首先把区间按左端点排序&#xff0c;然后右端点有两种情况。 假设是a区间&#xff0c;b区间。。。这样排列的顺序&#xff0c;那么 假设a[1]>b[0],如果a[1]>b[1]&#xff0c;就应该以b[1]为准&#xff0c;否则以a[1]为准。 class Solution { public:static bo…

老阳分享:视频号带货怎么做?有哪些方法?

在数字化浪潮中&#xff0c;视频号带货成为了一种新兴的商业模式&#xff0c;它结合了视频内容的吸引力和电商销售的便捷性&#xff0c;为品牌和商家带来了无限商机。那么&#xff0c;视频号带货究竟应该怎么做?又有哪些有效的方法呢? 首先&#xff0c;视频号带货的核心在于内…

行为管理设置能监控或者检测哪些东西

3 月 27 日&#xff0c;国新办举行“推动高质量发展”系列主题新闻发布会&#xff0c;浙江省省长王浩&#xff1a;全省市场经营主体 1040 万户&#xff0c;相当于平均每 6.5 个浙江人就有 1 个老板。 不由让小编想到&#xff0c;这么多老板&#xff0c;那么老板创办企业也怪不容…

【JavaEE】初识线程,线程与进程的区别

文章目录 ✍线程是什么&#xff1f;✍线程和进程的区别✍线程的创建1.继承 Thread 类2.实现Runnable接口3.匿名内部类4.匿名内部类创建 Runnable ⼦类对象5.lambda 表达式创建 Runnable ⼦类对象 ✍线程是什么&#xff1f; ⼀个线程就是⼀个 “执行流”. 每个线程之间都可以按…

大数据开发(离线实时音乐数仓)

大数据开发&#xff08;离线实时音乐数仓&#xff09; 一、数据库与ER建模1、数据库三范式2、ER实体关系模型 二、数据仓库与维度建模1、数据仓库&#xff08;Data Warehouse、DW、DWH&#xff09;1、关系型数据库很难将这些数据转换成企业真正需要的决策信息&#xff0c;原因如…