Linux通过 Docker 可以托管 (1),最新整理《Linux运维架构师面试题解析大全》

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注运维)
img

正文

docker build -t niksoper/netcore-books .
docker run -it niksoper/netcore-books

你应该看到程序能够和之前一样的运行,不过这一次我们不需要像之前那样安装源代码,因为源代码已经包含在 docker 镜像里面了。

暴露并发布端口

这个 API 并不是特别有用,除非我们需要从容器外面和它进行通信。 Docker 已经有了暴露和发布端口的概念,但这是两件完全不同的事。

据 Docker 官方文档:
EXPOSE指令通知 Docker 容器在运行时监听特定的网络端口。EXPOSE指令不能够让容器的端口可被主机访问。要使可被访问,你必须通过 -p 标志来发布一个端口范围或者使用 -p 标志来发布所有暴露的端口
EXPOSE 指令只是将元数据添加到镜像上,所以你可以如文档中说的认为它是镜像消费者。从技术上讲,我本应该忽略 EXPOSE 5000 这行指令,因为我知道 API 正在监听的端口,但把它们留下很有用的,并且值得推荐。

在这个阶段,我想直接从主机访问这个 API ,因此我需要通过-p 指令来发布这个端口,这将允许请求从主机上的端口 5000 转发到容器上的端口 5000,无论这个端口是不是之前通过 Dockerfile 暴露的。

docker run -d -p 5000:5000 niksoper/netcore-books

通过 -d 指令告诉 docker 在分离模式下运行容器,因此我们不能看到它的输出,但是它依旧会运行并监听端口 5000。你可以通过 docker ps来证实这件事。

因此,接下来我准备从主机向容器发起一个请求来庆祝一下:

curl http://localhost:5000/api/books

它不工作。

重复进行相同 curl 请求,我看到了两个错误:要么是 curl: (56) Recv failure: Connection reset by peer,要么是 curl: (52) Empty reply from server。

我返回去看 docker run 的文档,然后再次检查我所使用的 -p 选项以及 Dockerfile 中的 EXPOSE指令是否正确。我没有发现任何问题,这让我开始有些沮丧。

重新振作起来以后,我决定去咨询当地的一个 Scott Logic DevOps 大师 - Dave Wybourn(也在这篇 Docker Swarm 的文章里提到过),他的团队也曾遇到这个实际问题。这个问题是我没有配置过 Kestral,这是一个全新的轻量级、跨平台 web 服务器,用于 .NET Core 。

默认情况下, Kestrel 会监听 http://localhost:5000。但问题是,这儿的localhost是一个回路接口。

据维基百科:
在计算机网络中,localhost 是一个代表本机的主机名。本地主机可以通过网络回路接口访问在主机上运行的网络服务。通过使用回路接口可以绕过任何硬件网络接口。
当运行在容器内时这是一个问题,因为 localhost 只能够在容器内访问。解决方法是更新 Startup.cs里的 Main 方法来配置 Kestral 监听的 URL:

public static void Main(string[] args)
{
  var host = new WebHostBuilder()
    .UseKestrel()
    .UseContentRoot(Directory.GetCurrentDirectory())
    .UseUrls("http://*:5000") // 在所有网络接口上监听端口 5000
    .UseIISIntegration()
    .UseStartup<Startup>()
    .Build();

  host.Run();
}

通过这些额外的配置,我可以重建镜像,并在容器中运行应用程序,它将能够接收来自主机的请求:

docker build -t niksoper/netcore-books .
docker run -d -p 5000:5000 niksoper/netcore-books
curl -i http://localhost:5000/api/books

我现在得到下面这些相应:

HTTP/1.1 200 OK
Date: Tue, 30 Aug 2016 15:25:43 GMT
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Kestrel

[{"id":"1","title":"RESTful API with ASP.NET Core MVC 1.0","author":"Nick Soper"}]

在产品环境中运行 KESTREL

微软的介绍:
Kestrel 可以很好的处理来自 ASP.NET 的动态内容,然而,网络服务部分的特性没有如 IIS,Apache 或者 Nginx 那样的全特性服务器那么好。反向代理服务器可以让你不用去做像处理静态内容、缓存请求、压缩请求、SSL 端点这样的来自 HTTP 服务器的工作。
因此我需要在我的 Linux 机器上把 Nginx 设置成一个反向代理服务器。微软介绍了如何发布到 Linux 生产环境下的指导教程。我把说明总结在这儿:

  1. 通过 dotnet publish 来给应用程序产生一个自包含包。
  2. 把已发布的应用程序复制到服务器上
  3. 安装并配置 Nginx(作为反向代理服务器)
  4. 安装并配置 supervisor(用于确保 Nginx 服务器处于运行状态中)
  5. 安装并配置 AppArmor(用于限制应用的资源使用)
  6. 配置服务器防火墙
  7. 安全加固 Nginx(从源代码构建和配置 SSL)

这些内容已经超出了本文的范围,因此我将侧重于如何把 Nginx 配置成一个反向代理服务器。自然地,我通过 Docker 来完成这件事。

在另一个容器中运行NGINX

我的目标是在第二个 Docker 容器中运行 Nginx 并把它配置成我们的应用程序容器的反向代理服务器。

我使用的是来自 Docker Hub 的官方 Nginx 镜像。首先我尝试这样做:

docker run -d -p 8080:80 --name web nginx

这启动了一个运行 Nginx 的容器并把主机上的 8080 端口映射到了容器的 80 端口上。现在在浏览器中打开网址 http://localhost:8080 会显示出 Nginx 的默认登录页面。

现在我们证实了运行 Nginx 是多么的简单,我们可以关闭这个容器。

docker rm -f web

把 NGINX 配置成一个反向代理服务器

可以通过像下面这样编辑位于 /etc/nginx/conf.d/default.conf 的配置文件,把 Nginx 配置成一个反向代理服务器:

server {
  listen 80;

  location / {
    proxy_pass http://localhost:6666;
  }
}

通过上面的配置可以让 Nginx 将所有对根目录的访问请求代理到 http://localhost:6666。记住这里的 localhost 指的是运行 Nginx 的容器。我们可以在 Nginx容器内部利用卷来使用我们自己的配置文件:

docker run -d -p 8080:80 /
-v /path/to/my.conf:/etc/nginx/conf.d/default.conf /
nginx

注意:这把一个单一文件从主机映射到容器中,而不是一个完整目录。

在容器间进行通信

Docker 允许内部容器通过共享虚拟网络进行通信。默认情况下,所有通过 Docker 守护进程启动的容器都可以访问一种叫做“桥”的虚拟网络。这使得一个容器可以被另一个容器在相同的网络上通过 IP 地址和端口来引用。

你可以通过监测inspect容器来找到它的 IP 地址。我将从之前创建的 niksoper/netcore-books 镜像中启动一个容器并监测inspect它:

docker run -d -p 5000:5000 --name books niksoper/netcore-books
docker inspect books

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以看到这个容器的 IP 地址是 “IPAddress”: “172.17.0.3”。

所以现在如果我创建下面的 Nginx 配置文件,并使用这个文件启动一个 Nginx 容器, 它将代理请求到我的 API :

server {
  listen 80;

  location / {
    proxy_pass http://172.17.0.3:5000;
  }
}

现在我可以使用这个配置文件启动一个 Nginx 容器(注意我把主机上的 8080 端口映射到了 Nginx 容器上的 80 端口):

docker run -d -p 8080:80 /
-v ~/dev/nginx/my.nginx.conf:/etc/nginx/conf.d/default.conf /
nginx

一个到http://localhost:8080 的请求将被代理到应用上。注意下面 curl 响应的 Server 响应头:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

DOCKER COMPOSE

在这个地方,我为自己的进步而感到高兴,但我认为一定还有更好的方法来配置 Nginx,可以不需要知道应用程序容器的确切 IP 地址。另一个当地的 Scott Logic DevOps 大师 Jason Ebbin 在这个地方进行了改进,并建议使用 Docker Compose。

概况描述一下,Docker Compose 使得一组通过声明式语法互相连接的容器很容易启动。我不想再细说 Docker Compose 是如何工作的,因为你可以在之前的文章中找到。

我将通过一个我所使用的 docker-compose.yml 文件来启动:

version: '2'
services:
    books-service:
        container_name: books-api
        build: .

    reverse-proxy:
        container_name: reverse-proxy
        image: nginx
        ports:
         - "9090:8080"
        volumes:
         - ./proxy.conf:/etc/nginx/conf.d/default.conf

这是版本 2 语法,所以为了能够正常工作,你至少需要 1.6 版本的 Docker Compose。

这个文件告诉 Docker 创建两个服务:一个是给应用的,另一个是给 Nginx 反向代理服务器的。

BOOKS-SERVICE

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
这个与 docker-compose.yml 相同目录下的 Dockerfile 构建的容器叫做 books-api。注意这个容器不需要发布任何端口,因为只要能够从反向代理服务器访问它就可以,而不需要从主机操作系统访问它。

REVERSE-PROXY

这将基于 nginx 镜像启动一个叫做 reverse-proxy 的容器,并将位于当前目录下的 proxy.conf 文件挂载为配置。它把主机上的 9090 端口映射到容器中的 8080 端口,这将允许我们在http://localhost:9090上通过主机访问容器。

proxy.conf 文件看起来像下面这样:

server {
    listen 8080;

    location / {
      proxy_pass http://books-service:5000;
    }
}

这儿的关键点是我们现在可以通过名字引用books-service,因此我们不需要知道 books-api 这个容器的 IP 地址!

现在我们可以通过一个运行着的反向代理启动两个容器(-d意味着这是独立的,因此我们不能看到来自容器的输出):

docker compose up -d

验证我们所创建的容器:

docker ps

最后来验证我们可以通过反向代理来控制该 API :

curl -i http://localhost:9090/api/books

怎么做到的?

Docker Compose 通过创建一个新的叫做 mvclibrary_default 的虚拟网络来实现这件事,这个虚拟网络同时用于books-api 和 reverse-proxy 容器(名字是基于 docker-compose.yml 文件的父目录)。

通过docker network ls来验证网络已经存在:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

你可以使用 docker network inspect mvclibrary_default 来看到新的网络的细节:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意 Docker 已经给网络分配了子网:“Subnet”: “172.18.0.0/16”。/16 部分是无类域内路由选择(CIDR),完整的解释已经超出了本文的范围,但 CIDR 只是表示 IP 地址范围。运行 docker network inspect bridge 显示子网:“Subnet”: “172.17.0.0/16”,因此这两个网络是不重叠的。

现在用 docker inspect books-api 来确认应用程序的容器正在使用该网络:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后的话

最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!

资料预览

给大家整理的视频资料:

给大家整理的电子书资料:

如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
片转存中…(img-SbuLXygK-1713159381614)]

给大家整理的电子书资料:

[外链图片转存中…(img-yC0dPXFQ-1713159381615)]

如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)
[外链图片转存中…(img-tXXBZlnV-1713159381615)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值