用Docker或minikube(kubernetes)在容器中运行nginx,并模拟静态内容的发布过程
首先
以上所提到的信息与 CI/CD 相关。我希望能够以我在工作中接触到的环境和功能的身边信息来分享,因此开始了这篇文章的发布。在学习过程中,我们将选择不需要花费金钱的方式。
通过以下步骤,使用nginx的Docker镜像模拟运维人员使用静态内容进行发布的过程。
与人相关的环境和功能
这篇文章的目标读者如下所述。
-
- CI/CD 初学者
-
- プログラミング初学者
- 駆け出しエンジニア
以下是记录的环境和功能。
-
- nginx
-
- nginx.conf
-
- default.conf.template
-
- Docker
- minikube(kubernetes)
声明
我被要求设计使用nginx容器公开静态内容的特定部分。然后,我有点尴尬地去查了nginx的发音(是”恩吉恩艾克斯”吗?)。由于设计已经开始,时间很紧迫,我不知道该从哪里着手,但我正在努力保留最近查找到的信息。
起初,我听说过 Apache 作为一个 Web 服务器,可能是因为它作为一个著名的多用途工具而闻名。
这次选择了 “nginx”,可能是因为它被确认为处理 “静态内容” 的工具。
(大概可以说它擅长处理 “静态内容的展示”、”反向代理” 以及 “负载均衡器” 等功能的 Web 服务器吧。)
另外,在OpenShift和Kubernetes上访问其他卷也是初次尝试。
嗯,实际上,我在本地的Docker上也没有进行过挂载,这是我自学的结果。
计划或观点
我打算按照以下的流程继续进行。
-
- nginx のコンテナを動かす
-
- nginx のコンテナを Dockerfile で作って動かす
-
- nginx の利用上で必要になるであろう、port 番号やルートパスの指定方法を抑えておく
-
- 作った nginx イメージに Docker 上でマウントしてみる
- Docker でマウントする方法と、kubernetes でマウントする方法でどんな具合の差になるのかを抑えておく
也许,如果能够理解到这个程度,即使环境有所变化,也可以通过部分修改或其他方式应对。
前提任务
-
- ubuntu に Docker をインストールする Install Docker Engine on Ubuntu
minikube、kuectl のインストール
minikube Get Started!
Linux へ kubectl をインストールする
运行nginx容器
我首先查看的是Docker Hub上的nginx官方镜像。总之,我想尽快使其运行。
$ docker pull nginx:latest ※latestをプル
latest: Pulling from library/nginx
Digest: sha256:943c25b4b66b332184d5ba6bb18234273551593016c0e0ae906bab111548239f
Status: Image is up to date for nginx:latest
docker.io/library/nginx:latest
$ docker run -d -p 8080:80 nginx:latest ※起動
513779d0aaa6b8e3486a4809fa4aa1bd769a7bf78993255007ccf096c5f7238f
$ curl http://localhost:8080/ ※接続OK
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
使用 Dockerfile 创建并运行一个 Nginx 容器。
这里也可以使用原始的信息去了。
FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf
那么,nginx.conf 是设置文件对吧。是的,很感激。
刚才用启动的nginx查看了一下,如下所示。
嗯,这难道不是指定端口号和根路径的方法吗?
$ docker exec -it 0a3df5313506 bash
root@0a3df5313506:/# cat /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf; ※ここが怪しい
}
记住在nginx中,你可能需要指定端口号和根路径的方法。
这个主页上有写的。。懂的人可能知道,但对我来说有点难懂。。
So if you place templates/default.conf.template file, which contains variable references like this:
listen ${NGINX_PORT};
outputs to /etc/nginx/conf.d/default.conf like this:
listen 80;
没有default.conf.template这样的文件存在。
root@0a3df5313506:/etc/nginx# pwd
/etc/nginx
root@0a3df5313506:/etc/nginx# ls -la
total 48
drwxr-xr-x 1 root root 4096 Oct 25 10:23 .
drwxr-xr-x 1 root root 4096 Nov 13 03:05 ..
drwxr-xr-x 1 root root 4096 Nov 13 03:05 conf.d
-rw-r--r-- 1 root root 1007 Oct 19 07:56 fastcgi_params
-rw-r--r-- 1 root root 5349 Oct 19 07:56 mime.types
lrwxrwxrwx 1 root root 22 Oct 19 09:32 modules -> /usr/lib/nginx/modules
-rw-r--r-- 1 root root 648 Oct 19 09:32 nginx.conf
-rw-r--r-- 1 root root 636 Oct 19 07:56 scgi_params
-rw-r--r-- 1 root root 664 Oct 19 07:56 uwsgi_params
然而,存在conf.d/default.conf,并且在nginx.conf中的定义”include /etc/nginx/conf.d/*.conf; ※此处可能有问题”似乎是在读取它。
这样做”default.conf.template是将要注入到default.conf的环境变量变量化并自行配置”似乎是合理的。
实际尝试后,结果与预期相符。
FROM nginx
COPY static-html-directory /usr/share/nginx/html ※静的コンテンツを配置
COPY nginx.conf /etc/nginx/nginx.conf ※ここは変更加えていませんが、後で外からも注入できるように一応コピー
COPY default.conf.template /etc/nginx/templates/default.conf.template ※default.conf を元に作ったテンプレートを配置
server {
listen ${NGINX_PORT}; ※ここにコンテナ起動時に注入する環境変数が入る想定
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /app;
省略
$ docker build -t oad3jp999/my-nginx:1.0.0 .
Sending build context to Docker daemon 14.85kB
Step 1/4 : FROM nginx
---> 76c69feac34e
Step 2/4 : COPY static-html-directory /usr/share/nginx/html
---> Using cache
---> 00de7b966f5c
Step 3/4 : COPY nginx.conf /etc/nginx/nginx.conf
---> Using cache
---> c0a6076cded2
Step 4/4 : COPY default.conf.template /etc/nginx/templates/default.conf.template
---> 35f5ff0e0e9e
Successfully built 35f5ff0e0e9e
Successfully tagged oad3jp999/my-nginx:1.0.0
$ docker run -d \
> -it \
> -p 8080:81 \ ※コンテナの81番ポートに、外より8080でつながる
> --name my-nginx \
> --env NGINX_PORT=81 \ ※コンテナ起動時に注入するポート番号
> oad3jp999/my-nginx:1.0.0
b4d4e29956b8fa146e6bbfc9e2d02dfd455d506e8379aa0bcdb7f36813d871a6
$
$ curl http://localhost:8080/ ※接続OK
hello this is static-text from docker coppy
在Docker上尝试将创建的nginx镜像挂载上去。
试着稍微改变一下模板。
server {
listen ${NGINX_PORT};
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /app; ※コンテナ内の何も入っていない/appにマウントしていきます
# root /usr/share/nginx/html;
index send.txt; ※/appに置いたsend.txtがindexとして読みだされる想定
# index index.html index.htm send.txt;
}
使用Docker进行构建,并重新布置模板。
$ docker build -t oad3jp999/my-nginx:1.0.0 .
Sending build context to Docker daemon 13.82kB
Step 1/4 : FROM nginx
---> 76c69feac34e
Step 2/4 : COPY static-html-directory /usr/share/nginx/html
---> Using cache
---> 00de7b966f5c
Step 3/4 : COPY nginx.conf /etc/nginx/nginx.conf
---> Using cache
---> c0a6076cded2
Step 4/4 : COPY default.conf.template /etc/nginx/templates/default.conf.template
---> 39f088b173e2
Successfully built 39f088b173e2
Successfully tagged oad3jp999/my-nginx:1.0.0
$ docker run -d \
> -it \
> -p 8080:81 \
> --name my-nginx \
> --mount type=bind,source="$(pwd)"/target,target=/app,readonly \ ※ここで、ホストマシン側の「"$(pwd)"/target」を、コンテナ内の「/app」へマウント
> --env NGINX_PORT=81 \
> oad3jp999/my-nginx:1.0.0
cc97265d50624a1d5455665b83c1af58f288ca067e07c454269b7ca659c2a0c1
$ curl http://localhost:8080/ ※接続OK
hello this is mount target with nginx!
add text
$ docker exec -it my-nginx bash
root@cc97265d5062:/# cat /app/send.txt ※ディレクトリがマウントされて、send.txtなるファイルがルートアクセスで表示。ホスト側で「add text」を追記したらコンテナ側でも認識OK
hello this is mount target with nginx!
add text
root@cc97265d5062:/#
请记住在Docker中挂载的方法和在Kubernetes中挂载的方法之间的区别。
结论是在容器启动时指定挂载相似。(从Docker的理念来看,重视环境无关性,因此,在容器启动时进行指定似乎是一个好主意。我同意这个观点。)接下来是存在多个可连接存储的问题,只需将”volumes”的写法与OpenShift的PVC进行比较并做出修改,应该就可以搞定了。因此,使用minikube来进行准备工作。
$ minikube start --driver=docker ※minikube起動
* Ubuntu 20.04 上の minikube v1.22.0
* プロフィールを元に、 docker ドライバを使用します
* コントロールプレーンのノード minikube を minikube 上で起動しています
* イメージを Pull しています...
* 既存の docker container を "minikube" のために再起動しています...
* Docker 20.10.7 で Kubernetes v1.21.2 を準備しています...
* Kubernetes コンポーネントを検証しています...
- イメージ kubernetesui/metrics-scraper:v1.0.4 を使用しています
- イメージ kubernetesui/dashboard:v2.1.0 を使用しています
- イメージ gcr.io/k8s-minikube/storage-provisioner:v5 を使用しています
* 有効なアドオン: storage-provisioner, default-storageclass, dashboard
! /usr/local/bin/kubectl is version 1.23.5, which may have incompatibilites with Kubernetes 1.21.2.
- Want kubectl v1.21.2? Try 'minikube kubectl -- get pods -A'
* 完了しました! kubectl が「"minikube"」クラスタと「"default"」ネームスペースを使用するよう構成されました
$ cd /tmp
$ mkdir hostpath_pv ※マウント用ディレクトり作成
$ ls -la
合計 96
drwxrwxrwt 21 root root 4096 11月 13 12:54 .
drwxr-xr-x 21 root root 4096 3月 14 2021 ..
drwxrwxr-x 2 senju senju 4096 11月 13 12:54 hostpath_pv
$ cd hostpath_pv
$ vi send.txt
$ cat send.txt
This is mount from hostpath for minikube! ※マウントされた際には、nginxがこちらを返す想定
$ cd ..
$ minikube mount /tmp/hostpath_pv:/host ※前段として、minikubeのVMが認識するようにマウントしておく必要がある模様
* Mounting host path /tmp/hostpath_pv into VM as /host ...
- マウントタイプ:
- ユーザー ID: docker
- グループ ID: docker
- バージョン: 9p2000.L
- メッセージのサイズ: 262144
- Permissions: 755 (-rwxr-xr-x)
- Options: map[]
- アドレスをバインドします: 192.168.58.1:40645
* Userspace file server: ufs starting
* Successfully mounted /tmp/hostpath_pv to /host ※ホストマシンの「/tmp/hostpath_pv」が「/host」としてマウントされた
* NOTE: This process must stay alive for the mount to be accessible ...
准备用于挂载 Pod 的 yml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: oad3jp999/my-nginx:1.0.0
name: nginx
env:
- name: NGINX_PORT ※テンプレートで変数化したポート番号を環境変数として注入
value: "81"
volumeMounts:
- name: storage
mountPath: /app ※nginxの「/app」にマウントする。⇒ルートディレクトリに指定してあるので、例の「send.txt」なるものが読まれる。
volumes:
- name: storage
hostPath: ※本来、kubernetesではホストパスのストレージマウントは極めて限定的な目的での利用とされているが、いまはymlの書きっぷりが把握したいので、うってつけ
path: /host ※ホストマシンの「/tmp/hostpath_pv」がマウントされた「/host」を指定
type: DirectoryOrCreate ※直アクセス、無ければ作る
悬浮式盒子连接成功。
$ kubectl apply -f my-nginx.yml
pod/nginx created
$ kubectl get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx 1/1 Running 0 7s 172.17.0.5 minikube <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 28h <none>
$ kubectl exec -it nginx bash ※面倒なので、中から突きます
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx:/# curl http://localhost:81/ ※接続OK
This is mount from hostpath for minikube! ※想定通り!
root@nginx:/#
相关文章
-
- CI/CD とは?
-
- Azure Devops (Artifacts) を無償、無料で使う
-
- Spring Tool Suite 4 インストール、Spring Initializr 、gradlew の利用
-
- Spring Boot Web アプリケーションを作る
-
- Jar の Library を作り、Azure Artifacts を利用して成果物を配布する
-
- ライブラリ開発者より指定されたバージョンを利用してアプリを作る
-
- アプリを Docker 、Docker Compose でコンテナを動かしてみる
-
- Azure Devops (PileLines) を無償、無料で使う
-
- Azure Devops (PileLines) でテスト、ビルド、イメージプッシュをする
-
- minikube(kubernetes) でコンテナを動かしてみる
- nginx のコンテナを Docker や minikube(kubernetes) で動かし、静的コンテンツ公開工程を模倣