Docker容器构建最佳实践
nanshan 2024-12-02 23:24 4 浏览 0 评论
在容器和虚拟化广泛流行的今天,如何构建出一个安全、洁净的容器是大家都关心的问题。和安全领域对系统的要求一样"只安装必须的应用"的最小化原则也是容器构建的基本法则。一方面最小化的应用可以减小镜像的大小,节省上传下载的时间,同时减少了容器中的应用也就减少了可入侵点,使容器更安全。本文介绍我们给大家介绍了一套总结了业界实践的容器的最佳实践。目的是让容器构建更加快速,更安全,也更具弹性。本文假设读者有一定Docker和Kubernetes了解,但也可以单独作为Docker容器构建守则。
一个容器一个应用程序
当开始使用容器时,常见的一个误区是把容器当成虚拟机来使。这样做往往会让他们不能轻易满足某些需求而非常痛苦,同时也背离了容器的最大优势点。很多初学者在群里问了很多为么:为什么Docker不能aaa?怎么实现Docker bbb?然后他需要的答案其实上只是需要一个虚拟。虽然现代容器已经可以满足这些需求,但是这会极大减弱容器模型的大多数优点。以经典的Apache/MySQL/PHP堆栈为例,你可能很想在一个容器中运行所有组件。但是,最佳实践是使用两个或三个不同的容器:Apache容器,MySQL容器,和运行PHP-FPM的php容器。
由于容器设计思想是容器和托管的应用程序具有相同的生命周期,因此每个容器应当只包含一个应用程序。当容器启动时,应用程序随之启动,当容器停止时,应用也会停止。
容器如果部署了多个应用,则它们有可能具有不同的生命周期或处于不同的状态。例如,一个正在运行的容器,但其核心组件之一突然崩溃或无响应。由于没有额外的运行状况检查,整个容器管理系统(Docker或Kubernetes)将无法判断容器是否健康。在Kubernetes集群中,容器默认是不会重启的。
有些公共镜像中可能会使用如下有一些的操作,但不遵循原则:
使用进程管理系统(比如supervisor)来管理容器中的一个或多个应用。使用bash脚本作为容器中的入口点,并使其产生多个应用程序作为后台作业。
信号处理,PID 1和僵尸进程
Linux信号是控制容器内进程生命周期的主要方法。为了与前一条最佳实践保持一致,为了将应用程序的生命周期和容器关连,请确保应用程序能够正确处理Linux信号。其中最重要的一个Linux信号是SIGTERM,因为它用来终止进程。应用可能还会收到SIGKILL信号,用于非正常地终止进程,或者SIGINT信号,用于接受,键入的Ctrl + C指令。
进程标识符(PID)是Linux内核为每个进程提供的唯一标识符。 PID具有名称空间,容器具有自己的一组PID,这些PID会被映射到宿主机系统的PID。Linux内核启动时会创建第一个进程具有PID1。用来init系统用来管理其他进程,比如systemd或SysV。同样,容器中启动的第一个进程也是PID1。Docker和Kubernetes使用信号与容器内的进程进行通信。Docker和Kubernetes都只能向容器内具有PID 1的进程发送信号。
在容器环境中,需要考虑两个PIDs和Linux信号的问题。
Linux内核如何处理信号?
Linux内核处理PID 1的进程方式与对其他进程不同。PID1,不会自动注册信号量SIGTERM,所以SIGTERM或SIGINT默认对PID 1无效。默认必须使用SIGKILL信号来杀掉进程,无法优雅的关闭进程,可能会导致错误,监视数据写入中断(对于数据存储)以及一些不必要的告警。
典型的初始化系统如何处理孤立进程?
典型的初始化系统(例如systemd)也用被用来删除(捕获)孤立的僵尸进程。僵尸进程(其父进程已死亡的进程)将会被附加到具有PID 1的进程下,被其捕获关闭。但是在容器中,需要映射到容器PID 1的进程来处理。如果该进程无法正确处理,则可能会出现内存不足或其他资源不足的风险。
面对这些问题有几种常见的解决方案:
以PID 1运行并注册信号处理程序
该方案用来解决第一个问题。如果应用以受控方式生成子进程(通常是这种情况)是有效的,可以避免第二个问题。最简单方法是在Dockerfile中使用CMD和/或ENTRYPOINT指令启动你的进程。例如,下面的Dockerfile中,nginx是第一个也是唯一要启动的进程。
FROM debian:9
RUN apt-get update && \
apt-get install -y nginx
EXPOSE 80
CMD [ "nginx", "-g", "daemon off;" ]
注意:Nginx进程注册其自己的信号处理程序。使用此解决方案,在许多情况下,你必须在应用程序代码中执行相同的操作。
有时可能需要准备容器中的环境以使进程正常运行。在这种情况下,最佳实践是让容器在启动时运行shell初始化脚本。该Shell脚本的用来配置所需的环境并启动主要进程。但是,如果采用这种方法,则shell脚本拥有PID 1,这就是为什么必须使用内置exec命令从shell脚本启动进程的原因。exec命令将脚本替换为所需的程序,进程将继承PID 1。
在Kubernetes中启用进程名称空间共享
为Pod启用进程名称空间共享时,Kubernetes对该Pod中的所有容器使用单个进程名称空间。 Kubernetes Pod基础容器成为PID 1,并自动捕获孤立的进程。
使用专门的初始化系统
就像在更经典的Linux环境中一样,也可以使用init系统来解决这些问题。但是,如果用于这个目的,普通的初始化系统(例如systemd或SysV)太复杂且太重,建议使用专门的容器创建的初始化系统(例如tini)。
如果使用容器专用的初始化系统,则初始化进程具有PID 1,并执行以下操作:
注册正确的信号处理程序。
确保信号对你的应用程序有效。
捕获所有僵尸进程。
可以通过使用docker run命令的--init选项在Docker中使用此解决方案。要在Kubernetes中使用,则必须在容器镜像中先安装init系统,并将其用作容器的入口。
优化Docker构建缓存
Docker的构建缓存可以极大的加速容器镜像的构建。在容器系统中镜像是逐层构建的,在Dockerfile中,每条指令都会在镜像中创建一个层。在构建期间,如果可能,Docker会尝试重用先前构建中一层,尽可能跳过其底层来减少构建消耗成本的步骤。Docker只有在所有先前的构建步骤都使用它的情况下,才能使用其构建缓存。尽管这种做法通常使构建更快,但需要考虑一些情况。
例如,要充分利用Docker构建缓存,必须将需要经常更改的构建步骤放在Dockerfile的后面。如果将它们放在前面,则Docker无法将其构建缓存用于其他更改频率较低的构建步骤。通常为源代码的每个新版本构建一个新的Docker镜像,所以应尽可能在Dockerfile的后面将源代码添加到镜像。如下图,你可以看到,如果要更改了STEP 1,则Docker只能重用FROM FROM debian:9步骤中的层。但是,如果更改STEP 3,则Docker可以将这些层重新用于STEP 1和STEP 2。
图中蓝色表示可以重用的层,红色表示必须重建的层。层的重用原则导致另一个后果,如果构建步骤依赖于存储在本地文件系统上的任何类型的缓存,则该缓存必须在同一构建步骤中生成。如果未生成此缓存,则可能会使用来自先前构建的过期的缓存来执行的构建步骤。通过apt或yum等程序包管理器中最常有这个问题,必须在一个RUN命令中同时安装所有必须要的库。如果更改下面Dockerfile中的第二个RUN步骤,则不会重新运行apt-get update命令,从而导致过期的apt缓存。
FROM debian:9
RUN apt-get update
RUN apt-get install -y nginx
而是,在单个RUN步骤中合并两个命令:
FROM debian:9
RUN apt-get update && \
apt-get install -y nginx
删除不必要的工具
为了保护你的应用免受攻击者的侵害,请尝试通过删除所有不必要的工具来减少应用的攻击面。例如,删除诸如netcat之类的实用程序,因为可以用necat随便就能构建一个反向shell。如果容器中不安装netcat,则攻击者无法这样简单利用。
即使没有容器化,此最佳实践也适用于任何工作负载。区别在于,与经典虚拟机或裸机服务器相比,使用容器实现起来要容易得多。
其中一些工具可能对于调试有用。例如,如果你将此最佳实践推得足够远,那么详尽的日志,跟踪,概要分析和应用程序性能管理系统将成为必不可少的。实际上,你不再可以依赖本地调试工具,因为它们通常具有很高的特权。
文件系统内容
镜像中应尽可能少的保留内容。如果可以将应用程序编译为单个静态链接的二进制文件,则将该二进制文件添加到暂存镜像中将使获得最终镜像,该镜像仅包含一个应用程序,无其他内容。通过减少镜像中打包的工具数量,可以减少潜在的可在容器中执行的操作。
文件系统安全
镜像中没有工具是不够的。必须防止潜在的攻击者安装工具。可以在此处组合使用两种方法:
首先,避免以root用户身份在容器内运行。该方法提供了第一层安全性,并且可以防止攻击者使用嵌入在镜像中的包管理器(如apt-get或apk)修改root拥有的文件。为了使用该方法,必须禁用或卸载sudo命令。
以只读模式启动容器,可以通过使用docker run命令中的--read-only标志或使用Kubernetes中的readOnlyRootFilesystem选项来执行此操作。可以使用PodSecurityPolicy在Kubernetes中强制执行此操作。
注意:如果应用需要将临时数据写入磁盘,也可以使用readOnlyRootFilesystem选项,只需为临时文件添加emptyDir卷。Kubernetes中不支持emptyDir卷上的挂载,所以不能在启用noexec标志的情况下挂载该卷。
最小化镜像
生成较小的镜像具有诸如更快的上载和下载时间等优点,这对于Kubernetes中pod的冷启动时间尤为重要:镜像越小,节点下载就越快。但是,构建小型镜像很难,因为可能会在无意中给最终镜像引入了构建依赖项或未优化的镜像层。
使用最小的基础镜像
基础镜像是Dockerfile中FROM指令中所引用的镜像。Dockerfile中的所有指令均基于该镜像构建。基础镜像越小,生成的镜像就越小,下载和加载就越快。例如,alpine:3.7镜像比centos:7镜像就小好几十M。
我们甚至还可使用 scratch基础镜像,这是一个空镜像,可以在其上构建自己的运行时环境。如果需要运行的应用程序是静态链接的二进制文件,使用暂存基础镜像非常容易:
FROM scratch
COPY mybinary /mybinary
CMD [ "/mybinary" ]
GoogleContainerTools的Distroless项目提供了多种语言(Java,Python(3),Golang,Node.js,dotnet)的基础镜像。镜像仅包含语言的运行时,剔除了Linux发行版的很多工具,例如Shell,应用包管理器等,下面项目的一个Golang的列子:
减少镜像无效删减
要减小镜像的大小,需要严格遵守只安装必须的应用的原则。可能有时候需要临时安装一些工具的软件包,使用后在后面的步骤中再删除。但是,这种方法也是有问题的。因为Dockerfile的每条指令都会创建一个镜像层,创建后,再在稍后的步骤中删除的方法,实际不能减少镜像的大小。(数据还在,只是被隐藏在底层而已)。比如:
错误Dockerfile
FROM debian:9
RUN apt-get update && \
apt-get install -y \
[buildpackage]
RUN [build my app]
RUN apt-get autoremove --purge \
-y [buildpackage] && \
apt-get -y clean && \
rm -rf /var/lib/apt/lists/*
正确Dockerfile
FROM debian:9
RUN apt-get update && \
apt-get install -y \
[buildpackage] && \
[build my app] && \
apt-get autoremove --purge \
-y [buildpackage] && \
apt-get -y clean && \
rm -rf /var/lib/apt/lists/*
在错误版本Dockerfile中,[buildpackage]和/var/lib/ap /lists/*中的文件仍然存在于与第一个RUN相对应的镜像层中。该层是镜像的一部分,尽管里面的数据在最终镜像中不可访问,但也会和其他镜像层一起上传和下载。
在正确版本Dockerfile中,所有操作都在构建的应用程序的同一层中完成。 /var/lib/apt/lists/*中的[buildpackage]和文件在最终镜像中不会存在,真正起到了删除的效果。
减少镜像无效删除的另一种方法是使用多阶段构建(Docker 17.05中引入)。多阶段构建允许在第一个"构建"容器中构建应用程序,并在使用相同Dockerfile的同时在另一个容器中使用结果。
在下面的Dockerfile中,hello二进制文件内置在第一个容器中,并注入了第二个容器。因为第二个容器是从头开始的,所以生成的镜像仅包含hello二进制文件,而不包含构建期间所需的源文件和目标文件。但是,二进制文件是必须静态链接才能正常工作。
FROM golang:1.10 as builder
WORKDIR /tmp/go
COPY hello.go ./
RUN CGO_ENABLED=0 go build -a -ldflags '-s' -o hello
FROM scratch
CMD [ "/hello" ]
COPY --from=builder /tmp/go/hello /hello
尝试创建具有公共镜像层的镜像
如果必须下载Docker镜像,则Docker首先检查镜像中是否已经包含某些层。如果你具有这些镜像层,就不会下载。如果以前下载的其他镜像与当前下载的镜像具有相同的基础镜像,则当前镜像的下载数据量会少很多。
在企业内部,可以为开发人员提供一组通用的标准基础镜像来减少必要的下载。系统只会下载每个基础镜像一次,初始下载后,只需要使每个镜像中不同的镜像层,镜像的共同层越多,下载速度就越快。如下图中红色框的基础镜像就只需下载一次。
容器注册表进行漏洞扫描
对服务器和虚拟机,软件漏洞扫描是常用的一个安全手段,通过集中式软件扫描系统,列出了每台主机上安装的软件包和存在的漏洞源,并及时通知管理员修补漏洞,比如虫虫之前的文章中介绍过的Flan Scan系统。
由于容器原则上是不可变的,所以不建议对存在漏洞的情况下对其进行漏洞修补。最佳实践是对其重建镜像,打包补丁程序,然后重新部署。与服务器相比,容器的生命周期要短得多,身份标识的定义要好得多。因此,使用类似的集中检测容器中漏洞的一种不好的方法。
为了解决这个问题,可以在托管镜像的容器注册表(Container Registry)中进行漏洞扫描。这样就可以在发现容器镜像中的漏洞。将镜像上传到注册表时或漏洞库更新时,就会进行扫描,或者启动计划任务定期扫描。
检测到漏洞后,可以使用脚本来触发自动漏洞修补过程。最好是结合版本管理(比如Gitlab)CI/CD管道来持续进行镜像构建来进行漏洞修补。一般步骤如下:
1.将镜像存储在容器注册表中并启用漏洞扫描。
2.配置一个作业,该作业定期从容器注册表中获取新漏洞,并在需要时触发镜像重建。
3.构建新镜像后,通过持续部署系统CD来将镜像部署到验证环境中。
4.手动检查验证是否正常。
5.如果未发现问题,请手动推送灰度部署到生产环境。
正确标记镜像
Docker镜像通常由两个部分标识:它们的名称和标签。例如,对于centos:8.0.1镜像,centos是名称,而8.0.1是标签。如果在Docker命令中未提供最新标签,则默认使用最新标签。名称和标签对在任何给定时间都是应该唯一的。但是,可以根据需要将标签重新分配给其他镜像。构建镜像时,需要正确标记,遵循统一一致标记策略。
容器镜像是一种打包和发布软件的方法。标记镜像可让用户识别软件的特定版本进行下载。因此,将容器镜像上的标记系统关系到软件的发布策略。
使用语义版本标记
发行软件的常用方法是使用语义化版本号规范(The Semantic Versioning Specification)版本号来"标记"(如git tag命令中的)特定版本的源代码。语义化版本号规范是为了改善各种软件版本号格式混乱,语义不明的现状由semver.org提出的一种处理版本号的规整方法。在该规范中软件版本号由三部分构成:X.Y.Z,其中:
X是主要版本,有向下不兼容的修改或者颠覆性的更新时增加。
Y是次要版本,有向下兼容的修改或者添加兼容性的新功能时增加1。
Z是补丁程序版本,仅仅是打一些兼容性补丁,做一些兼容性修复时增加。
次要版本号或补丁程序版本号中的每个增量都必须是向后兼容的更改。
如果该系统或类似系统,请按照以下策略标记镜像:
最新标签始终指的是最新(可能稳定)的镜像。创建新镜像后,该标签即被移动。
X.Y.Z标签是指软件的特定版本。请不要将其移动到其他镜像。
X.Y标记是指软件X.Y次要分支的最新修补程序版本。当发布新的补丁程序版本时,它将被移动。
X标记是指X主要分支的最新次要版本的最新补丁程序版本。当发布新的修补程序版本或新的次要版本时,它将移动。
使用此策略可以使用户灵活地选择他们要使用的软件版本。他们可以选择特定的X.Y.Z版本,并确保镜像永不更改,或者可以通过选择不太具体的标签来自动获取更新。
用Git提交哈希标记
如果你用持续交付系统并且经常发布软件,则可能不能使用语义版本控制规范中描述的版本号。在这种情况下,处理版本号的常用方法是使用Git commit SHA-1哈希(或它的简短版本)作为版本号。根据设计原理,Git的提交哈希是不可变的,并引用到软件的特定版本。
可以将git提交哈希用作软件的版本号,也可以用作软件特定版本构建的Docker镜像的标记。这样可以使Docker镜像具有可追溯性,在这种情况下image标记是不可变的,因此可以立即知道给定容器中正在运行哪个特定版本的软件。在持续交付管道中,自动更新用于部署的版本号。
权衡公共镜像的使用
Docker的一大优点是可用于各种软件的大量公共可用镜像。这些镜像使你可以快速入门。但是,在为线上环境设计容器策略时,可能会遇到一些限制,使得公共提供的镜像无法满足要求。以下是可能导致无法使用公共镜像的一些限制示例:
精确控制镜像内部的内容。
不想依赖外部存储库。
想严格控制生产环境中的漏洞。
每个镜像都需要相同的基础操作系统。
对所有这些限制的对策都是相同的,并且但是有很高的代价,那就是必须构建自己的镜像。对于数量有限的镜像,可以自己构,但是当数目有增长的时。为了有机会大规模管理这样的系统,可以考虑使用以下方法:
以可靠的方式自动生成镜像,即使对于很少生成的镜像也是如此。
解决镜像漏洞,可以在容器注册表中漏洞扫描。企业中不同团队创建的镜像执行内部标准的方法。有几种工具可用来帮助在生成和部署的镜像上实施策略:
container-diff:可以分析镜像的内容,甚至可以比较两个镜像之间的镜像。
container-structure-test:可以测试镜像的内容是否符合定义一组规则。
Grafeas:是一种工件元数据API,可以在其中存储有关镜像的元数据,以便以后检查这些镜像是否符合你的策略。
Kubernetes具有准入控制器,在Kubernetes中部署工作负载之前,可以使用该准入控制器检查许多先决条件。
Kubernetes还具有Pod安全策略,可用于在群集中强制使用安全选项。
也能采用一种混合系统:使用诸如Debian或Alpine之类的公共镜像作为基础镜像,然后基于该镜像构建其他镜像。或者可能想将公共镜像用于某些非关键镜像,并为其他情况构建自己的镜像。
关于软件可
在Docker镜像中包含第三方库和软件包之前,请确保相应的许可允许这样做。第三方许可证可能还会对重新分发施加限制,当将Docker镜像发布到公共注册表时,这些限制就适用。
总结
本文中介绍了容器构建过程中应该遵循的一些基本的原则,通过这些原则可以确保构建的容器安全、精炼,可收缩,可控,当然这些条款也只是建议性质的,在满足需求的基础上请尽量遵循。其中涉及的一些方法仅供参考,你也可以在遵守基本原则情况下使用更适合自己的解决方法。
相关推荐
- 今晚拿下PHP反序列化的一系列操作
-
引言在CTF中反序列化类型的题目还是比较常见的,之前有学习过简单的反序列化,以及简单pop链的构造。这次学习内容为php内置的原生类的反序列化以及一点进阶知识。在题目给的的代码中找不到可利用的类时,这...
- Win10安装Apache和PHP(apache安装php模块)
-
说明:虽然PHPStudy之类的软件给我们提供了方便的集成环境,但是其使用的是非线程安全的PHP版本(NotThreadSafe,NTS),某些功能不可以使用。所以,我们还需要自己再安装一个Apa...
- 腾讯云云函数部署laravel项目(腾讯云函数 selenium)
-
1、购买函数套餐包在Serverless控制台,选择函数套餐包进行购买2、新建函数服务2.1、模板创建选择函数URL:新建函数URL,启用公网访问:2.1.1、postman访问首页2.1.2、pos...
- 站长教你搭建属于自己的网站(站长教你搭建属于自己的网站是什么)
-
每个人都希望可以有自己的网站,因为那样高端大气上档次,低调奢华有内涵,尤其是公司用户,一般会有自己的网站。而个人呢,也可以搭建自己的网站博客,论坛等,但是一般个人都是搭建博客的。好了,那么下面站长教你...
- 微信公众号开发出现 cURL error 60: SSL certificate problem ssl证书
-
在phpstudy的环境下如果出现这样的报错cURLerror60:SSLcertificateproblem:unabletogetlocalissuercertificat...
- 【网络安全】关于PHP Study nginx解析高危漏洞的预警通报
-
网络安全近日,山石网科安全研究院监测发现PHPStudyWindows最新版本存在nginx解析漏洞,可以造成任意代码执行。一、漏洞情况phpStudy是一个PHP调试环境的程序集成包,该程序包集成...
- PHP 环境 搭建教程(php环境搭建教程linux)
-
PHP是一种编程语言,很多网站都用PHP语言编写,我们有时候需要测试一个网站,就需要PHP环境才能运行,又要安装Apache、又要安装MySQL……真的非常麻烦。其实我们可以使用PHP集成...
- 黑客搭建钓鱼平台,手把手教你如何钓鱼?
-
跨站脚本攻击XSS:通过HTML注入篡改了网页,插入了恶意的脚本,从而用户浏览网页时,控制用户浏览器的一种攻击那么,我们搭建一个XSS钓鱼平台吧,注意:这个平台仅用于学习和测试,小伙伴们不要动有坏心思...
- php源码网站搭建方法和过程(php网站源码完整)
-
web网站是我们上网的窗口,而网站是如何搭建的呢?今天我们来做一个介绍,以php代码为例来进行介绍(后续会介绍一下java代码搭建,如果想要我这里涉及的工具或源码请私信我)。1、首先你需要去网上下载你...
- 使用VS Code调试PhpStudy环境里的代码
-
最近几个月把所有项目都迁过来VSCode了(除了因为Unity调试问题反而用回了VisualStudio),PHP也就抛弃了最强的PhpStorm。这段时间抽空在帮朋友处理PHP项目,然...
- phpstudy搭建PHP+Mysql服务(用phpstudy搭建服务器)
-
PHP是一种创建动态交互性站点的强有力的服务器端脚本语言。PHP是免费的,并且使用非常广泛。同时,对于像微软ASP这样的竞争者来说,PHP无疑是另一种高效率的选项。(1)PHP环境搭建使用V...
- Windows安装phpstudy(Windows安装mysql)
-
说明:phpstudy是一个PHP+MySQL+Apache的集成环境,可以减少单独部署各个所需软件的麻烦,以及更加方便地切换版本。phpenv、wamp等软件的作用一样。由于环境的不同,安装过程中可...
- phpstudy安装及简单使用教程(phpstudy安装教程详解)
-
phpstudy前不久爆出有后门,我的看法是,去看下是哪个版本有后门,为啥会有后门,怎么解决掉这个后门,而不是听到后门就弃用了。毕竟phpstudy绿色安装,配置简单,多版本融合,真香。前言:关于开发...
- 如何对dedeCMS的开源程序进行二次开发
-
二次开发,简单的说就是在现有的软件上进行定制修改,功能的扩展,然后达到自己想要的功能和效果,一般来说都不会改变原有系统的内核。为了让更多人了解二次开发,并更方便的了解DedeCMS的二次开发,下面将会...
- mysql基础问题三问(底层逻辑;正在执行;日志观察)
-
背景:经常面试会遇到且实际工作中也会应用到的三个场景:目录:一.mysql查询时的底层原理是什么?二.如何查看正在执行的mysql语句?三.如何观察mysql运行过程中的日志信息?-----...
你 发表评论:
欢迎- 一周热门
-
-
极空间如何无损移机,新Z4 Pro又有哪些升级?极空间Z4 Pro深度体验
-
如何在安装前及安装后修改黑群晖的Mac地址和Sn系列号
-
爱折腾的特斯拉车主必看!手把手教你TESLAMATE的备份和恢复
-
10个免费文件中转服务站,分享文件简单方便,你知道几个?
-
日本海上自卫队的军衔制度(日本海上自卫队的军衔制度是什么)
-
[常用工具] OpenCV_contrib库在windows下编译使用指南
-
【系统配置】信创终端挂载NAS共享全攻略:一步到位!
-
UOS服务器操作系统防火墙设置(uos20关闭防火墙)
-
Ubuntu系统Daphne + Nginx + supervisor部署Django项目
-
WindowsServer2022|配置NTP服务器的命令
-
- 最近发表
-
- 今晚拿下PHP反序列化的一系列操作
- Win10安装Apache和PHP(apache安装php模块)
- 腾讯云云函数部署laravel项目(腾讯云函数 selenium)
- 站长教你搭建属于自己的网站(站长教你搭建属于自己的网站是什么)
- 微信公众号开发出现 cURL error 60: SSL certificate problem ssl证书
- 【网络安全】关于PHP Study nginx解析高危漏洞的预警通报
- PHP 环境 搭建教程(php环境搭建教程linux)
- 黑客搭建钓鱼平台,手把手教你如何钓鱼?
- php源码网站搭建方法和过程(php网站源码完整)
- 使用VS Code调试PhpStudy环境里的代码
- 标签列表
-
- linux 查询端口号 (58)
- docker映射容器目录到宿主机 (66)
- 杀端口 (60)
- yum更换阿里源 (62)
- internet explorer 增强的安全配置已启用 (65)
- linux自动挂载 (56)
- 禁用selinux (55)
- sysv-rc-conf (69)
- ubuntu防火墙状态查看 (64)
- windows server 2022激活密钥 (56)
- 无法与服务器建立安全连接是什么意思 (74)
- 443/80端口被占用怎么解决 (56)
- ping无法访问目标主机怎么解决 (58)
- fdatasync (59)
- 405 not allowed (56)
- 免备案虚拟主机zxhost (55)
- linux根据pid查看进程 (60)
- dhcp工具 (62)
- mysql 1045 (57)
- 宝塔远程工具 (56)
- ssh服务器拒绝了密码 请再试一次 (56)
- ubuntu卸载docker (56)
- linux查看nginx状态 (63)
- tomcat 乱码 (76)
- 2008r2激活序列号 (65)