在运行Docker的主机上显示主机名的Nginx容器

首先

在使用Kubernetes进行工作时,我创建了一个容器,用于确定在浏览器上连接的容器是在哪个Worker上运行的。我会有意停止Worker来检查连接目标。

我已经确认了操作环境。

    • Raspberry Pi 4

 

    • Ubuntu 20.04

 

    Docker 19.03.13

形象

我已经将其上传到 https://hub.docker.com/r/yasthon/nginx-display-hostname。

试着动一动

在这里,我们正运行在主机名为”dockerhost.example.jp”的环境中。

$ docker pull yasthon/nginx-display-hostname
$ docker container run -d -v /etc/hostname:/usr/share/nginx/html/hostname -p 80:80 yasthon/nginx-display-hostname
$ curl http://localhost/index.sh
<html><head>
<title>dockerhost.example.jp</title>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head><body>
HOSTNAME : dockerhost.example.jp
</body></html>

我将从浏览器中确认。
访问 http://[Docker主机的IP地址]/index.sh。

HOSTNAME : dockerhost.example.jp

行动

在容器启动时,将/etc/hostname挂载。
使用Nginx运行sh,并读取主机名。

Dockerfile => 镜像文件

这是在本地构建时使用的文件。

FROM debian:buster-slim

COPY default.conf /etc/nginx/conf.d/

COPY index.sh /usr/share/nginx/html/

RUN apt-get update && \
  apt-get install -y --no-install-recommends nginx fcgiwrap && \
  apt-get autoclean && \
  rm -rf /var/lib/apt/lists/* && \
  echo "daemon off;" >> /etc/nginx/nginx.conf && \
  rm -f /etc/nginx/sites-enabled/default && \
  chmod 744 /usr/share/nginx/html/index.sh && \
  chown www-data:www-data /usr/share/nginx/html/index.sh

CMD /etc/init.d/fcgiwrap start && nginx

当我在普通的操作系统上安装时,它非常顺利地运行,但在容器中执行时出现了问题。

    • Nginxのdefault rootは/usr/share/nginx/html/だと思いこんでいたら、/var/www/htmlを参照していました。コンテナの用途が限定的なので、調査はせずに/etc/nginx/sites-enabled/defaultを削除することで解決しました。

fcgiwrap.socketが無かったです。CMDに /etc/init.d/fcgiwrap startを追加してコンテナ起動時に作成しています。
permissionエラーでました。chmodとchownを追加しました。
DockerHubからpullしたNginx Official イメージでは、思うように動作できなかったです。パッケージでインストールを行い動作させました。

默认配置文件.conf

这是Nginx的配置文件。

server {
  listen       80;
  server_name  localhost;
  location ~ \.sh$ {
    root   /usr/share/nginx/html/;
    include           /etc/nginx/fastcgi_params;
    fastcgi_index     index.sh;
    fastcgi_param     SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    fastcgi_pass      unix:/var/run/fcgiwrap.socket;
  }
}

相比Dockerfile,没有任何问题。

index.sh 索引.sh

读取并显示已装载的hostname文件。

#!/bin/sh

host_name=$(cat hostname)

echo "Content-type:text/html"
echo ""
echo "<html><head>"
echo "<title>${host_name}</title>"
echo '<meta http-equiv="Content-type" content="text/html;charset=UTF-8">'
echo "</head><body>"
echo "HOSTNAME : ${host_name}"
echo "</body></html>"

同样,没有任何问题。

本地构建

我将镜像名称设为”nginx-display-hostname”。将三个文件放置在同一目录中,然后执行docker build命令。

$ docker image build -t nginx-display-hostname .
$ docker container run -d -v /etc/hostname:/usr/share/nginx/html/hostname -p 80:80 nginx-display-hostname
$ curl http://localhost/index.sh
<html><head>
<title>dockerhost.example.jp</title>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head><body>
HOSTNAME : dockerhost.example.jp
</body></html>

我会从浏览器上确认。
访问http://[Docker主机的IP地址]/index.sh。

HOSTNAME : dockerhost.example.jp

运行在Kubernetes上

需要使用volumeMounts和volumes来挂载/etc/hostname。

apiVersion: v1
kind: Namespace
metadata:
  name: nginx-prod # namespace の名前
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment # deployment の名前(replicaset の名前もこれになる)
  namespace: nginx-prod # namespace の名前
spec:
  selector:
    matchLabels: # ラベルがマッチしたPodを対象とするreplicasetの作成
      app: nginx-pod
  replicas: 2
  template: # Pod のテンプレート
    metadata:
      name: nginx-pod # Pod の名前
      namespace: nginx-prod # Pod のnamespace の名前
      labels: # Pod のラベル
        app: nginx-pod
    spec:
      containers: # コンテナの設定
        - name: nginx-container # コンテナの名前
          image: yasthon/nginx-display-hostname # イメージの名前
          env:
            - name: nginx-container
          ports:
            - containerPort: 80 # コンテナのポート
          volumeMounts:
            - name: file-hostname
              mountPath: /usr/share/nginx/html/hostname
      volumes:
        - name: file-hostname
          hostPath:
            path: /etc/hostname

我会启动Pod。

$ kubectl apply -f sample.yaml
namespace/nginx-prod created
deployment.apps/nginx-deployment created

我会确认Pod的名字。

$ kubectl get all -n nginx-prod
NAME                                    READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-7ff4cc65cd-6r4qv   1/1     Running   0          3m52s
pod/nginx-deployment-7ff4cc65cd-djm9r   1/1     Running   0          3m52s

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   2/2     2            2           3m53s

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-7ff4cc65cd   2         2         2       3m53s

在Pod的详细信息中查看IP。

$ kubectl describe pod/nginx-deployment-7ff4cc65cd-djm9r -n nginx-prod | grep ^IP:
IP:           10.244.1.5

工人会从上方访问确认过的IP地址。

$ curl http://10.244.1.5/index.sh
<html><head>
<title>worker.example.jp</title>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head><body>
HOSTNAME : worker.example.jp
</body></html>

我确认 Pod(nginx-deployment-7ff4cc65cd-6r4qv) 正在 worker.example.jp 主机上运行。
如果要从集群外用浏览器访问,您将需要一个 Service。

最后

我立刻開始製作,但花了比預期更多的時間。如果能幫到需要的人,我將感到非常幸福。

bannerAds