使用Docker(Mac)搭建 Nginx/Openresty - Kafka - kafkaManager

2022-01-02 雲時代架構

本文默認讀者已經對Docker有一定了解,且清楚使用Docker進行部署的優勢。


1.安裝Docker(Mac)


官網:https://docs.docker.com/docker-for-mac/install/


1.1 下載 Docker for Mac

地址:https://store.docker.com/editions/community/docker-ce-desktop-mac


1.2 下載完成以後,雙擊打開文件Docker.dmg

image.png


1.3雙擊Docker.app啟動

image.png

Mac頂部狀態欄會出現鯨魚圖標

image.png


1.4點擊鯨魚圖標可以進行設置

image.png


1.5 Check versions

$ docker --version
Docker version 18.03, build c97c6d6

$ docker-compose --version
docker-compose version 1.21.2, build 8dd22a9

$ docker-machine --version
docker-machine version 0.14.0, build 9ba6da9


1.6 Hello Word


1.6.1 打開命令行終端,通過運行簡單的Docker映像測試您的安裝工作。

$ docker run hello-world

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
ca4f61b1923c: Pull complete
Digest: sha256:ca0eeb6fb05351dfc8759c20733c91def84cb8007aa89a5bf606bc8b315b9fc7
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.
...


1.6.2 啟動Dockerized web server

$ docker run -d -p 80:80 --name webserver nginx


1.6.3 打開瀏覽器,輸入http://localhost/

image.png

常用命令:

docker ps 查看正在運行的容器

docker stop停止正在運行的容器

docker start啟動容器

docker ps -a查看終止狀態的容器

docker rm -f webserver命令來移除正在運行的容器

docker list 列出本地鏡像

docker rmi 刪除的鏡像


2.使用Docker安裝Nginx


Docker Store 地址:https://store.docker.com/images/nginx

其實在上文中Hello World即已經安裝了nginx。


2.1 拉取 image
2.2 創建Nginx容器

docker run --name mynginx -p 80:80  -v /Users/gaoguangchao/Work/opt/local/nginx/logs:/var/log/nginx   -v /Users/gaoguangchao/Work/opt/local/nginx/conf.d:/etc/nginx/conf.d  -v /Users/gaoguangchao/Work/opt/local/nginx/nginx.conf:/etc/nginx/nginx.conf:ro -v /Users/gaoguangchao/Work/opt/local/nginx/html:/etc/nginx/html  -d nginx

-d 以守護進程運行(運行在後臺)
--name nginx  容器名稱;
-p 80:80  埠映射
-v 配置掛載路徑 宿主機路徑:容器內的路徑


關於掛載

為了能直接修改配置文件,以實現對Nginx的定製化,需要進行Docker的相關目錄掛在宿主機上。

需要掛載的目錄/文件:/etc/nginx/conf.d   /etc/nginx/nginx.conf /etc/nginx/html

有一點尤其需要注意,當掛載的為文件而非目錄時,需要注意以下兩點:

a. 掛載文件命令: -v  宿主機路徑:容器內的路徑:ro

b.宿主機需要先創建後文件,無法自動創建,反之將報錯


nginx.conf 示例


worker_processes  1;








events {
   worker_connections  1024;
}


http {
   include       mime.types;
   default_type  application/octet-stream;


   

   sendfile        on;
   

   
   keepalive_timeout  65;

   

   upstream demo {

       server 127.0.0.1:8080;

   }

   server {
       listen       80;
       server_name  request_log;

       location / {
           root   html;
           
           proxy_connect_timeout   3;  
           proxy_send_timeout      30;  
           proxy_read_timeout      30;  
           proxy_pass http://demo;
       }

       
       

       
       
       error_page   500 502 503 504  /50x.html;
       location = /50x.html {
           root   html;
       }
   }
}


2.3 瀏覽器訪問

image.png

在調試過程中往往不會很順利,這裡的技巧是通過閱讀error.log中的異常日誌進行


2.4 配置反向代理

此處是本機啟動一個 SpringBoot web server,埠為:8080,瀏覽器訪問:http://localhost:8080/index/hello

image.png

按照上節中nginx.conf示例中的配置方式,增加upstream、server、proxy_pass相關配置,對80埠進行監聽,重啟nginx容器。

瀏覽器訪問:http://localhost/index/hello,可以看到正常訪問。


3.使用Docker安裝Openresty


Openresty是在Nginx基礎上做了大量的定製擴展,其安裝過程和Nginx基本一致。

Docker Store 地址:https://store.docker.com/community/images/openresty/openresty


3.1 拉取 image

docker pull openresty/openresty


3.2 創建Openresty容器

docker run -d --name="openresty" -p 80:80 -v /Users/gaoguangchao/Work/opt/local/openresty/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf:ro -v /Users/gaoguangchao/Work/opt/local/openresty/logs:/usr/local/openresty/nginx/logs   -v /Users/gaoguangchao/Work/opt/local/openresty/conf.d:/etc/nginx/conf.d -v /Users/gaoguangchao/Work/opt/local/openresty/html:/etc/nginx/html openresty/openresty

注意事項和安裝Nginx基本一致,在此不再贅述。


4.使用Docker安裝Kafka


Docker Store 地址:https://store.docker.com/community/images/spotify/kafka


4.1 拉取 image

docker pull spotify/kafka


4.2 創建Kafka容器

運行命令:

docker run -p 2181:2181 -p 9092:9092 --env ADVERTISED_HOST=`127.0.0.1` --env ADVERTISED_PORT=9092 spotify/kafka

2181為zookeeper埠,9092為kafka埠

輸出啟動日誌:

image.png


4.3 Check zookeeper是否啟動

可以使用一些可視化客戶端連接埠,進行監控,如zooInspector、Idea Zookeeper Plugin等

zooInspector示例

Idea Zookeeper Plugin


5.使用Docker安裝Kafka Manager


Kafka Manager 是Yahoo開源的kafka監控和配置的web系統,可以進行kafka的日常監控和配置的動態修改。

Docker Store 地址:https://store.docker.com/community/images/sheepkiller/kafka-manager


5.1 拉取 image

docker pull sheepkiller/kafka-manager


5.2 創建Kafka Manager容器

運行命令:

docker run -it --rm  -p 9000:9000 -e ZK_HOSTS="127.0.0.1:2181" -e APPLICATION_SECRET=letmein sheepkiller/kafka-manager

2181為上節中部署的zookeeper埠,9000為kafka-manager的web埠

輸出啟動日誌:

image.png


5.3 訪問Kafka Manager

瀏覽器訪問:http://localhost:9000
按照頁面上的操作按鈕進行kafka集群的註冊,具體使用方式再次不做詳細介紹。

image.png

註冊配置後的界面:

image.png


6.Kafka消息生產與消費
6.1創建maven項目

** pom依賴**

<dependencies>
       <dependency>
           <groupId>org.slf4j</groupId>
           <artifactId>jcl-over-slf4j</artifactId>
           <version>${org.slf4j-version}</version>
           <scope>runtime</scope>
       </dependency>
       <dependency>
           <groupId>org.apache.logging.log4j</groupId>
           <artifactId>log4j-1.2-api</artifactId>
           <version>${log4j2-version}</version>
       </dependency>
       <dependency>
           <groupId>org.apache.logging.log4j</groupId>
           <artifactId>log4j-slf4j-impl</artifactId>
           <version>${log4j2-version}</version>
       </dependency>
       <dependency>
           <groupId>org.apache.logging.log4j</groupId>
           <artifactId>log4j-api</artifactId>
           <version>${log4j2-version}</version>
       </dependency>
       <dependency>
           <groupId>org.apache.logging.log4j</groupId>
           <artifactId>log4j-core</artifactId>
           <version>${log4j2-version}</version>
       </dependency>
       <dependency>
           <groupId>com.lmax</groupId>
           <artifactId>disruptor</artifactId>
           <version>3.2.0</version>
       </dependency>
     

       <dependency>
           <groupId>org.apache.kafka</groupId>
           <artifactId>kafka-clients</artifactId>
           <version>0.10.1.0</version>
       </dependency>
   </dependencies>


6.2 增加log4j2配置

配置log4j2為能正常列印debug日誌,方便進行異常排查   (重要)
在resources目錄下增加log4j2.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration status="WARN">
   <Properties>
       <Property name="pattern_layout">%d %-5p (%F:%L) - %m%n</Property>
       <Property name="LOG_HOME">/logs</Property>
   </Properties>

   <appenders>
       <Console name="CONSOLE" target="SYSTEM_OUT">
           <PatternLayout pattern="%d %-5p (%F:%L) - %m%n"/>
       </Console>


   </appenders>
   <loggers>
       <root level="debug" includeLocation="true">
           <appender-ref ref="CONSOLE"/>
       </root>
   </loggers>
</configuration>

關於log4j2的使用,有興趣的可以了解:Log4j1升級Log4j2實戰


6.3 創建生產者示例

package com.moko.kafka;

import org.apache.kafka.clients.producer.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Properties;

public class MokoProducer extends Thread {

   private static final Logger LOGGER = LoggerFactory.getLogger(MokoProducer.class);

   private final KafkaProducer<String, String> producer;
   private final String topic;
   private final boolean isAsync;

   public MokoProducer(String topic, boolean isAsync) {
       Properties properties = new Properties();
       properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "78c4f4a0f989:9092");
       properties.put(ProducerConfig.CLIENT_ID_CONFIG, "MokoProducer");
       properties.put(ProducerConfig.ACKS_CONFIG, "all");
       properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
       properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");

       this.producer = new KafkaProducer<String, String>(properties);
       this.topic = topic;
       this.isAsync = isAsync;
   }

   @Override
   public void run() {
       int seq = 0;

       while (true) {
           String msg = "Msg: " + seq;

           if (isAsync) {
               producer.send(new ProducerRecord<String, String>(this.topic, msg));
           } else {
               producer.send(new ProducerRecord<String, String>(this.topic, msg),
                       new MsgProducerCallback(msg));
           }

           seq++;
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
   }

   
   class MsgProducerCallback implements Callback {

       private final String msg;

       public MsgProducerCallback(String msg) {
           this.msg = msg;
       }

       public void onCompletion(RecordMetadata recordMetadata, Exception e) {
           if (recordMetadata != null) {
               LOGGER.info(msg + " be sended to partition no : " + recordMetadata.partition());
           } else {
               LOGGER.info("recordMetadata is null");
           }

           if (e != null)
               e.printStackTrace();
       }
   }


   public static void main(String args[]) {
       new MokoProducer("access-log", false).start();
   }
}


簡單運行後,列印日誌如下:

image.png


6.4 創建消費者示例

package com.moko.kafka;

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.Properties;

public class MokoCustomer {

   private static final Logger LOGGER = LoggerFactory.getLogger(MokoCustomer.class);


   public static void main(String args[]) throws Exception {


       String topicName = "access-log";
       Properties props = new Properties();
       KafkaConsumer<String, String> consumer = getKafkaConsumer(props);
       consumer.subscribe(Arrays.asList(topicName));
       while (true) {
           ConsumerRecords<String, String> records = consumer.poll(100);
           if (!records.isEmpty()) {
               LOGGER.info("=========================");
           }
           for (ConsumerRecord<String, String> record : records) {
               LOGGER.info(record.value());
           }
       }
   }

   private static KafkaConsumer<String, String> getKafkaConsumer(Properties props) {
       props.put("bootstrap.servers", "172.18.153.41:9092");
       props.put("group.id", "group-1");

       props.put("enable.auto.commit", "true");
       props.put("auto.commit.interval.ms", "1000");
       props.put("session.timeout.ms", "30000");
       props.put("key.deserializer",
               "org.apache.kafka.common.serialization.StringDeserializer");
       props.put("value.deserializer",
               "org.apache.kafka.common.serialization.StringDeserializer");
       return new KafkaConsumer<String, String>(props);
   }
}


簡單運行後,列印日誌如下:

image.png


6.5 注意事項

由於是在本機使用Docker搭建的環境,遇到最多的問題就是網絡問題,如host等的配置,但是只要意識到這點,通過注意分析各種異常日誌,便不難排查解決。

項目目錄結構


7.結語

致此,本文就介紹完了如何使用Docker搭建 Nginx/Openresty  -  Kafka - kafkaManager。

後續將會繼續介紹如何使用Docker搭建一套 nginx+lua+kafka實現的日誌收集的教程,敬請期待。

個人介紹:

高廣超:多年一線網際網路研發與架構設計經驗,擅長設計與落地高可用、高性能、可擴展的網際網路架構。

本文首發在 高廣超的簡書博客


相關焦點

  • 老朱:Kafka入門教程(1)
    3本文將採用docker容器作為實驗的環境,虛擬機太佔用資源。首先安裝Docker,Docker為Windows、Mac都提供了安裝包 Docker Desktop. 安裝即可用,這個包涵了多個docker組件,包括 docker compose、docker swarm、docker-machine,有興趣的可以深入了解一下。
  • docker安裝Nginx和Tomcat
    #使用docker ps 查看一下啟動中的鏡像docker psuwsgi_paramsroot@9f435eb63bed:/etc/nginxdocker安裝tomcatdocker run -it --rm tomcat:9.0#--rm 這裡代表的意思是用完即刪除 這裡刪除的是容器,但是鏡像還在# tomcat:9.0指定tomcat9.0的版本 不加就直接使用最新的tomcat
  • 初探Docker的網絡模式
    macvlan的網絡模式,docker會為容器的虛擬網絡接口分配MAC地址。創建一個macvlan網絡$ docker network create -d macvlan 啟動一個busybox容器,網絡模式是macvlan
  • Kafka Streams開發入門(4)
    功能演示說明今天依然使用表徵一個電影的消息類型,格式如下:{"name": "Meryl Streep", "title": "The Iron Lady", "genre": "drama"}{"name": "Will Smith", "title": "Men in Black", "genre": "comedy"}{"name
  • Kafka Streams開發入門(9)
    今天我為大家帶來時間窗口函數的使用方法。在Kafka Streams中,時間窗口有三類:固定時間窗口(Tumbling Window)、滑動時間窗口(Sliding Window)和會話窗口(Session Window)。我們不詳細討論這三類窗口的定義與區別,而是直接使用一個項目來說明如何利用Tumbling Window定期統計每部電影的打分人數。
  • 「事件驅動架構」GoldenGate創建從Oracle到Kafka的CDC事件流(2)
    前文:「事件驅動架構」GoldenGate創建從Oracle到Kafka的CDC事件流(1)步驟7/12:安裝並運行Apache Kafka從VM的桌面環境中打開Firefox並下載Apache Kafka(我使用的是kafka_2.11-2.1.1.tgz)。
  • Docker用法
    設置yum源為阿里雲sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo安裝docker後查看sudo yum install docker-ce -y;docker -v;
  • Spring Boot 2.0(五):Docker Compose+Spring Boot+Nginx+Mysql 實踐
    今天給大家演出的導演是 Docker 家族的 docker-compare ,主演是 Spring Boot、Nginx、Mysql 三位又紅又紫的大碗,名導名演在一起的時候往往是準備搞事情,接下來又一場經典大片值得大家期待。
  • 一文看懂Kafka消息格式的演變
    0    Leader: 0   Replicas: 0 Isr: 0然後往msg_format_v0中發送一條key="key",value="value"的消息,之後查看對應的日誌:[root@node1 kafka_2.10-0.8.2.1]# bin/kafka-run-class.sh kafka.tools.DumpLogSegments
  • 圖解SparkStreaming與Kafka的整合,細節滿滿
    我們要知道Spark作為實時計算框架,它僅僅涉及到計算,並沒有涉及到數據的存儲,所以我們後期需要使用spark對接外部的數據源。SparkStreaming作為Spark的一個子模塊,它有4個類型的數據源:socket數據源(測試的時候使用)HDFS數據源(會用到,但是用得不多)自定義數據源(不重要,沒怎麼見過別人會自定義數據源)擴展的數據源(比如kafka數據源,它非常重要,面試中也會問到)下面老劉圖解SparkStreaming與Kafka的整合,但只講原理,代碼就不貼了,網上太多了,老劉寫一些自己理解的東西
  • Dockerfile企業實戰教程
    一、dockerfile語法詳解Dockerfile 是一個用來構建鏡像的文本文件,文本內容包含了一條條構建鏡像所需的指令和說明。基於Dockerfile構建鏡像可以使用docker build命令。docker build命令中使用-f可以指定具體的dockerfile文件FROM centosMAINTAINER xianchaoRUN yum install wget -yRUN yum install nginx -yCOPY index.html /usr/share/nginx/html/EXPOSE 80ENTRYPOINT
  • 推薦給IT新手的11個Docker免費上手項目
    容器是完全使用沙箱機制,相互之間不會有任何接口。使用該工具可以方便的通過界面管理 docker 不用再記那些命令。安裝命令:5. docker-slim地址: http s:// github.com/docker-slim/docker-slimstar: 8.8kfork: 306自動縮減 docker 鏡像的體積的工具。
  • Flume系列 (二)Flume的實際操作--增量寫入Hive--自定義攔截器完成數據過濾--數據傳入kafka消費
    agent -n a3 -c conf -f /opt/flumeconf/conf_0805_interceptor2.properties -Dflume.root.logger=INFO,console第五步:將文件放入指定文件夾/opt/datas修改成功三:Flume傳輸數據生產給Kafka進行消費:第一步:創建Kafka的topic kafka-topics.sh
  • Docker操作必看,原來這才是正確打開Docker的新方式!
    你可以從本地構建一個鏡像,使用 docker build 命令,下文我們會說到如何構建自己的鏡像,我們先從鏡像倉庫中拉取鏡像,使用 docker pull 命令進行拉取,如下圖所示:docker pull nginx首先我們得找到 docker 的鏡像倉庫,網址:hub.docker.com
  • 雲計算核心技術Docker教程:解決Windows下docker埠映射問題
    在Windows系統下安裝docker並嘗試在其中運行Nginx服務,在映射完畢之後在主機的瀏覽器中,打開localhost:port無法訪問對應的服務。
  • Docker - 常用命令
    鏡像管理# 查看所有鏡像$ docker images# 搜索鏡像$ docker search nginx
  • Docker命令大整理,附示例!
    # 大寫P--rm                   # 容器退出後自動清理本容器,用於創建臨時容器-t                     # 為容器重新分配一個偽輸入終端,通常與 -i 同時使用# 示例# 使用鏡像nginx:latest以後臺模式啟動一個名為mynginx的容器,其中將容器外8080埠映射到容器內,主機目錄 /data 映射到容器內
  • 學習Docker就應該掌握的dockerfile語法與指令
    原有指令 MAINTAINER 已經放棄使用,用 LABEL maintainer="hogwarts@testing-studio.com" 替代。USER:指定運行容器時的用戶名或 UID,後續 RUN 也會使用指定用戶。RUN:RUN 命令是 Dockerfile 執行命令的核心部分。它接受命令作為參數並用於創建鏡像。
  • 我i愛love卡夫卡kafka
    wifi密碼是ilovekafka, 真想順著這名字,流浪到更遠。孟京輝2020首發原創戲劇作品《卡夫卡的夢》,將在大屋頂作為2020杭州國際戲劇節的開幕震撼上演,10月11日-13日連演三天,日日有新意,夜夜難自寐。
  • Kafka 3.0.0新功能get
    的棄用能夠在 Kafka Connect 的一次調用中重新啟動連接器的任務連接器日誌上下文和連接器客戶端覆蓋現在是默認啟用的增強了 Kafka Streams 中時間戳同步的語義修改了 Stream 的 TaskId 的公共 API在 Kafka Streams 中,默認的 serde 變成了 null,還有一些其他的配置變化更多詳情可查看:https://blogs.apache.org/kafka