<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>2025-01 on Funky Si's Test</title><link>https://blog-test.funkysi1701.com/2025/01/</link><description>Recent content in 2025-01 on Funky Si's Test</description><generator>Hugo -- gohugo.io</generator><language>en-gb</language><managingEditor>funkysi1701@gmail.com (Simon Foster)</managingEditor><webMaster>funkysi1701@gmail.com (Simon Foster)</webMaster><lastBuildDate>Mon, 27 Jan 2025 20:00:00 +0000</lastBuildDate><atom:link href="https://blog-test.funkysi1701.com/2025/01/index.xml" rel="self" type="application/rss+xml"/><item><title>Set up Grafana for .NET with Docker</title><link>https://blog-test.funkysi1701.com/posts/2025/setting-up-grafana/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 27 Jan 2025 20:00:00 +0000</pubDate><guid>https://blog-test.funkysi1701.com/posts/2025/setting-up-grafana/</guid><category term="Grafana">Grafana</category><category term="Monitoring">Monitoring</category><category term="Analytics">Analytics</category><category term="Docker">Docker</category><category term="Prometheus">Prometheus</category><category term="DotNet">DotNet</category><category term="DevOps">DevOps</category><category term="Metrics">Metrics</category><media:content medium="image" type="image/png" url="https://blog-test.funkysi1701.com/images/grafana-dashboard.png"/><description>&lt;p&gt;Grafana is an open-source analytics and monitoring platform that lets you query, visualise, and alert on metrics. It pairs well with Prometheus for scraping application endpoints. This post walks through a Docker Compose stack that monitors a simple .NET API.&lt;/p&gt;
&lt;h2 id="setting-up-grafana"&gt;Setting up Grafana&lt;a class="anchor ms-1" href="#setting-up-grafana" aria-label="Permalink: Setting up Grafana"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To visualise metrics data, we need a few components. The .NET application exposes a &lt;code&gt;/metrics&lt;/code&gt; endpoint. Prometheus scrapes it on an interval and stores the samples. Grafana then queries Prometheus and renders dashboards.&lt;/p&gt;
&lt;h3 id="docker-compose-file"&gt;Docker Compose File&lt;a class="anchor ms-1" href="#docker-compose-file" aria-label="Permalink: Docker Compose File"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Start with a Compose file for Prometheus and Grafana. Pin image tags so rebuilds stay reproducible (bump them when you deliberately upgrade):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;services&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;prometheus&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;prom/prometheus:v3.4.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;5431&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;9090&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;./prometheus/:/etc/prometheus/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;prometheus:/prometheus &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;grafana&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;grafana/grafana:11.6.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;expose&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;3000&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;3000&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;3000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;grafana:/var/lib/grafana&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;prometheus&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;grafana&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This brings up Grafana and Prometheus, maps ports, and mounts config/data volumes.&lt;/p&gt;
&lt;h3 id="prometheus-configuration"&gt;Prometheus Configuration&lt;a class="anchor ms-1" href="#prometheus-configuration" aria-label="Permalink: Prometheus Configuration"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Next, create a &lt;strong&gt;prometheus.yml&lt;/strong&gt; file to configure Prometheus:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;global&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;scrape_interval&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;15s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;evaluation_interval&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;15s &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;scrape_configs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;job_name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;api&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;scheme&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;https&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;tls_config&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;insecure_skip_verify&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;scrape_interval&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;10s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;scrape_timeout&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;5s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;static_configs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;targets&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#39;api.example.com:443&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This configures how often the &lt;code&gt;/metrics&lt;/code&gt; endpoint should be scraped. By default Prometheus expects something like &lt;code&gt;http://api.example.com/metrics&lt;/code&gt;. Because my API ran under HTTPS I set &lt;code&gt;scheme&lt;/code&gt; to &lt;code&gt;https&lt;/code&gt; and skipped TLS verification in this lab setup. &lt;code&gt;scrape_interval&lt;/code&gt; is how often the endpoint is scraped; if &lt;code&gt;scrape_timeout&lt;/code&gt; is omitted the global value is used.&lt;/p&gt;
&lt;p&gt;More information about configuring Prometheus can be found &lt;a href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/" target="_blank" rel="noopener noreferrer"&gt;here&lt;/a&gt;
.&lt;/p&gt;
&lt;h3 id="grafana-config"&gt;Grafana Config&lt;a class="anchor ms-1" href="#grafana-config" aria-label="Permalink: Grafana Config"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can now log into Grafana on &lt;a href="http://localhost:3000" target="_blank" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;
with the default username and password of &lt;code&gt;admin&lt;/code&gt;/&lt;code&gt;admin&lt;/code&gt;. You will be prompted to change the password. Add a Prometheus data source next. Prometheus is published on the host as &lt;a href="http://localhost:5431" target="_blank" rel="noopener noreferrer"&gt;http://localhost:5431&lt;/a&gt;
, but from another container you usually cannot use &lt;code&gt;localhost&lt;/code&gt; for a sibling service.&lt;/p&gt;
&lt;p&gt;If Grafana needs to reach Prometheus on the &lt;strong&gt;host&lt;/strong&gt; (for example when Prometheus is published only to the host network), use &lt;strong&gt;host.docker.internal&lt;/strong&gt; (Docker Desktop and many Linux setups with the host-gateway mapping): &lt;a href="http://host.docker.internal:5431" target="_blank" rel="noopener noreferrer"&gt;http://host.docker.internal:5431&lt;/a&gt;
. Prefer the Compose service name (&lt;code&gt;http://prometheus:9090&lt;/code&gt;) when both services share the same Compose network.&lt;/p&gt;
&lt;h3 id="dashboard"&gt;Dashboard&lt;a class="anchor ms-1" href="#dashboard" aria-label="Permalink: Dashboard"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The next thing we need to do is build a dashboard — the .NET team has done much of the hard work. They published a &lt;a href="https://devblogs.microsoft.com/dotnet/introducing-aspnetcore-metrics-and-grafana-dashboards-in-dotnet-8/" target="_blank" rel="noopener noreferrer"&gt;Grafana dashboard&lt;/a&gt;
you can import.&lt;/p&gt;
&lt;p&gt;You can also build panels yourself in the Grafana UI (graphs, gauges, and other visualisations).&lt;/p&gt;
&lt;p&gt;
&lt;img class="img-fluid" alt="Dashboard" src="https://blog-test.funkysi1701.com/images/2025/dashboard-screenshot.png" loading="lazy"
width="2471" height="1238"
/&gt;
&lt;/p&gt;
&lt;h2 id="metrics-endpoint"&gt;Metrics endpoint&lt;a class="anchor ms-1" href="#metrics-endpoint" aria-label="Permalink: Metrics endpoint"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If your .NET application is using .NET Aspire, this &lt;code&gt;/metrics&lt;/code&gt; endpoint is often already set up for you. Look in &lt;code&gt;Extensions.cs&lt;/code&gt; in your ServiceDefaults project for something like the following (you need the NuGet package &lt;code&gt;OpenTelemetry.Exporter.Prometheus.AspNetCore&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; WebApplication MapDefaultEndpoints(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt; WebApplication app)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// The following line enables the Prometheus endpoint (requires the OpenTelemetry.Exporter.Prometheus.AspNetCore package)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; app.MapPrometheusScrapingEndpoint();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you are not using .NET Aspire, you can add &lt;code&gt;app.MapPrometheusScrapingEndpoint()&lt;/code&gt; to your &lt;code&gt;Program.cs&lt;/code&gt; file (with the same package referenced).&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;a class="anchor ms-1" href="#conclusion" aria-label="Permalink: Conclusion"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With Compose, Prometheus, and Grafana in place you can scrape a .NET &lt;code&gt;/metrics&lt;/code&gt; endpoint and watch live dashboards — useful for latency, exceptions, and ASP.NET Core built-in meters. Happy monitoring!&lt;/p&gt;
&lt;h3 id="related-on-this-blog"&gt;Related on this blog&lt;a class="anchor ms-1" href="#related-on-this-blog" aria-label="Permalink: Related on this blog"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Prefer classic host and service checks? Try &lt;a href="https://blog-test.funkysi1701.com/posts/2025/monitoring-with-nagios-docker/"&gt;monitoring with Nagios in Docker&lt;/a&gt;
. If Aspire already wires OpenTelemetry for you, &lt;a href="https://blog-test.funkysi1701.com/posts/2024/aspire/"&gt;getting started with Aspire&lt;/a&gt;
is a useful companion to the metrics endpoint notes above.&lt;/p&gt;
&lt;p&gt;If you have enjoyed this article and want to get a monthly email with all my latest articles, please sign up to my &lt;a href="https://blog-test.funkysi1701.com/newsletter"&gt;newsletter&lt;/a&gt;
. If you have any questions or comments, please feel free to reach out or leave a comment below.&lt;/p&gt;</description></item><item><title>Adding Elasticsearch with .Net Aspire</title><link>https://blog-test.funkysi1701.com/posts/2025/adding-elasticsearch-with-aspire/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 20 Jan 2025 20:00:00 +0000</pubDate><guid>https://blog-test.funkysi1701.com/posts/2025/adding-elasticsearch-with-aspire/</guid><category term="Elasticsearch">Elasticsearch</category><category term="DotNet">DotNet</category><category term="Aspire">Aspire</category><category term="Search">Search</category><category term="Indexing">Indexing</category><category term="Development">Development</category><category term="Tech">Tech</category><media:content medium="image" type="image/jpeg" url="https://blog-test.funkysi1701.com/images/elastic-search.jpg"/><description>&lt;p&gt;A few weeks ago I talked about &lt;a href="https://blog-test.funkysi1701.com/posts/2024/aspire/"&gt;.Net Aspire&lt;/a&gt;
, well lets take a look at how we can use it with Elasticsearch. Elastic search is a powerful search engine that can be used to index and search data. It is built on top of Lucene and provides a powerful way to search through your data.&lt;/p&gt;
&lt;p&gt;Aspire allows dependencies like elasticsearch to be added to a project programmatically. Lets look at how this can work.&lt;/p&gt;
&lt;p&gt;Add this nuget package to your AppHost project (as of writing this is a preview package):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Include=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Aspire.Hosting.Elasticsearch&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Version=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;9.0.0-preview.5.24551.3&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In your AppHost project, add the following code to your &lt;code&gt;Program.cs&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; elasticsearch = builder
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .AddElasticsearch(&lt;span style="color:#e6db74"&gt;&amp;#34;elasticsearch&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now if you run your project it will add an elasticsearch containter to your project. A common way to administer elasticsearch is to use Kibana. You can add this to your project by adding the following code to your &lt;code&gt;Program.cs&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; kibana = builder
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .AddContainer(&lt;span style="color:#e6db74"&gt;&amp;#34;kibana&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;kibana&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;8.15.3&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// Add Kibana from the image kibana, and tag 8.15.3 and give it a name kibana&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .WithReference(elasticsearch) &lt;span style="color:#75715e"&gt;// Add a reference to the elasticsearch container&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .WithEndpoint(&lt;span style="color:#ae81ff"&gt;5601&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5601&lt;/span&gt;); &lt;span style="color:#75715e"&gt;// Expose a port so you can connect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now if you run your project you will have an elasticsearch and kibana container running. You can access kibana by going to &lt;code&gt;http://localhost:5601&lt;/code&gt;, and elasticsearch by going to &lt;code&gt;http://localhost:9200&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="troubleshooting-kibana"&gt;Troubleshooting Kibana&lt;a class="anchor ms-1" href="#troubleshooting-kibana" aria-label="Permalink: Troubleshooting Kibana"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;However when I do that I get the error &lt;code&gt;Kibana server is not ready yet&lt;/code&gt;. Looking at the kibana container logs, I see the following error:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-log" data-lang="log"&gt;2025-01-19T21:42:13 [2025-01-19T21:42:13.558+00:00][WARN ][plugins.security.config] Generating a random key for xpack.security.encryptionKey. To prevent sessions from being invalidated on restart, please set xpack.security.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.
Unable to retrieve version information from Elasticsearch nodes. security_exception
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is due to the security settings in Elasticsearch. To fix this, you can turn off this security feature by enabling an environment variable:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; elasticsearch = builder
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .AddElasticsearch(&lt;span style="color:#e6db74"&gt;&amp;#34;elasticsearch&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .WithEnvironment(&lt;span style="color:#e6db74"&gt;&amp;#34;xpack.security.enabled&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;false&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As Aspire is only running locally, this is fine, but in a production environment, you would want to secure your Elasticsearch and Kibana instances.&lt;/p&gt;
&lt;h2 id="using-elasticsearch-in-your-project"&gt;Using Elasticsearch in Your Project&lt;a class="anchor ms-1" href="#using-elasticsearch-in-your-project" aria-label="Permalink: Using Elasticsearch in Your Project"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that you have Elasticsearch added to your project, how can you use it? In the .NET project that wants to connect and interact with Elasticsearch, you can add the following NuGet package:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Aspire.Elastic.Clients.Elasticsearch (version 9.0.0-preview.5.24551.3 as of writing)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the &lt;code&gt;Program.cs&lt;/code&gt; file of your .NET project you can add the following code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;builder.AddElasticsearchClient(&lt;span style="color:#e6db74"&gt;&amp;#34;elasticsearch&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;No need to specify any complex connection strings or settings, Aspire will handle all of that for you.&lt;/p&gt;
&lt;p&gt;This is pretty much all of the Aspire specific code you need, but lets have a quick look at indexing some data and returning it with a search. Elastic Search has extensive &lt;a href="https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/examples.html" target="_blank" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;
on how to do this with the dotnet libraries.&lt;/p&gt;
&lt;p&gt;To index some data you can use the following code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; _client.Indices.CreateAsync(&lt;span style="color:#e6db74"&gt;&amp;#34;searchindex&amp;#34;&lt;/span&gt;, cancellationToken); &lt;span style="color:#75715e"&gt;// Create an index called searchindex&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; documents = context.Episode.ToList(); &lt;span style="color:#75715e"&gt;// Get the documents you want to index from Entity Framework or any other source&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; _client.IndexManyAsync(documents, index: &lt;span style="color:#e6db74"&gt;&amp;#34;searchindex&amp;#34;&lt;/span&gt;, cancellationToken); &lt;span style="color:#75715e"&gt;// Index the documents into the searchindex index&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ElasticsearchClient can be injected in via dependency injection, again no need to specify any connection strings or settings.&lt;/p&gt;
&lt;p&gt;To search for data you can use the following code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Create a search request with a wildcard query which searches in the title field of your indexed documents.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; searchRequest = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; ESSearchRequest(&lt;span style="color:#e6db74"&gt;&amp;#34;searchindex&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; From = &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Size = &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Query = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; WildcardQuery(&lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;) { Value = &lt;span style="color:#e6db74"&gt;$&amp;#34;*{SearchQuery}*&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Execute the search request and get the response.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; response = &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; _client.SearchAsync&amp;lt;Episode&amp;gt;(searchRequest, cancellationToken);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (response.IsValidResponse)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Return the documents from the response.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; response.Documents.ToList();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="conclusion"&gt;Conclusion&lt;a class="anchor ms-1" href="#conclusion" aria-label="Permalink: Conclusion"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;By following these steps, you can successfully integrate Elasticsearch and Kibana into your .NET Aspire project. This setup allows you to leverage powerful search and analytics capabilities in your application. Remember to secure your instances in a production environment to ensure data safety.&lt;/p&gt;</description></item><item><title>NuGet central package management</title><link>https://blog-test.funkysi1701.com/posts/2025/nuget-central-package-management/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 13 Jan 2025 20:00:00 +0000</pubDate><guid>https://blog-test.funkysi1701.com/posts/2025/nuget-central-package-management/</guid><category term="NuGet">NuGet</category><category term="PackageManagement">PackageManagement</category><category term="DotNet">DotNet</category><category term="Development">Development</category><category term="DevOps">DevOps</category><media:content medium="image" type="image/png" url="https://blog-test.funkysi1701.com/images/central-package-management-with-nuget.png"/><description>&lt;p&gt;Managing dependencies in .NET projects can become complex, especially when dealing with multiple projects that share common packages. NuGet Central Package Management (CPM) is a feature that simplifies this process by allowing you to manage package versions centrally.&lt;/p&gt;
&lt;h2 id="what-is-nuget-central-package-management"&gt;What is NuGet Central Package Management?&lt;a class="anchor ms-1" href="#what-is-nuget-central-package-management" aria-label="Permalink: What is NuGet Central Package Management?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;NuGet Central Package Management allows you to define and manage package versions in a central location, rather than specifying them individually in each project file. This approach ensures consistency across projects and simplifies the process of updating package versions.&lt;/p&gt;
&lt;h2 id="setting-up-central-package-management"&gt;Setting Up Central Package Management&lt;a class="anchor ms-1" href="#setting-up-central-package-management" aria-label="Permalink: Setting Up Central Package Management"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To get started with Central Package Management, follow these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a Directory.Packages.props File&lt;/strong&gt;: This file will contain the central package version definitions. Create this file in the root directory of your solution.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Define Package Versions&lt;/strong&gt;: In the &lt;code&gt;Directory.Packages.props&lt;/code&gt; file, define the package versions you want to manage centrally. For example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;Project&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;ManagePackageVersionsCentrally&amp;gt;&lt;/span&gt;true&lt;span style="color:#f92672"&gt;&amp;lt;/ManagePackageVersionsCentrally&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;PackageVersion&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Include=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Newtonsoft.Json&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Version=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;13.0.1&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;PackageVersion&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Include=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Serilog&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Version=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;2.10.0&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;PackageVersion&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Include=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Microsoft.EntityFrameworkCore&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Version=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;9.0.0&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;PackageVersion&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Include=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Microsoft.EntityFrameworkCore.SqlServer&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Version=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;9.0.0&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/Project&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Update all your csproj files&lt;/strong&gt;: In each project file (&lt;code&gt;.csproj&lt;/code&gt;), remove the version number information:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Include=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Newtonsoft.Json&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Include=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Serilog&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Include=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Microsoft.EntityFrameworkCore&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Include=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Microsoft.EntityFrameworkCore.SqlServer&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="benefits-of-central-package-management"&gt;Benefits of Central Package Management&lt;a class="anchor ms-1" href="#benefits-of-central-package-management" aria-label="Permalink: Benefits of Central Package Management"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Using Central Package Management offers several benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Consistency&lt;/strong&gt;: Ensures that all projects use the same package versions, reducing the risk of version conflicts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simplified Updates&lt;/strong&gt;: Updating a package version in the central file automatically updates it across all projects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced Maintenance&lt;/strong&gt;: Simplifies the process of managing package versions, especially in large solutions with many projects.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If for any reason you want to disable Central Package Management, you can set the &lt;code&gt;ManagePackageVersionsCentrally&lt;/code&gt; property to &lt;code&gt;false&lt;/code&gt; in the &lt;code&gt;Directory.Packages.props&lt;/code&gt; file, or in the csproj file if you only want to disable for a single project.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;a class="anchor ms-1" href="#conclusion" aria-label="Permalink: Conclusion"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;NuGet Central Package Management simplifies the process of managing package versions across multiple projects in a .NET solution. By defining package versions in a central file, you can ensure consistency, simplify updates, and reduce maintenance efforts. Give it a try in your next .NET project to experience the benefits firsthand.&lt;/p&gt;
&lt;p&gt;For more information, visit the &lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/Central-Package-Management" target="_blank" rel="noopener noreferrer"&gt;official NuGet documentation&lt;/a&gt;
.&lt;/p&gt;</description></item><item><title>Setting Up Nagios Monitoring with Docker</title><link>https://blog-test.funkysi1701.com/posts/2025/monitoring-with-nagios-docker/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 06 Jan 2025 20:00:00 +0000</pubDate><guid>https://blog-test.funkysi1701.com/posts/2025/monitoring-with-nagios-docker/</guid><category term="Nagios">Nagios</category><category term="Docker">Docker</category><category term="Monitoring">Monitoring</category><category term="SysAdmin">SysAdmin</category><category term="DevOps">DevOps</category><category term="NetworkMonitoring">NetworkMonitoring</category><media:content medium="image" type="image/png" url="https://blog-test.funkysi1701.com/images/nagios.png"/><description>&lt;p&gt;A long time ago in my SysAdmin days, I was a big fan of &lt;a href="https://blog-test.funkysi1701.com/posts/2014/i-love-nagios/"&gt;Nagios&lt;/a&gt;
. Recently, I decided to revisit it and see if I could run it in a Docker container to monitor my local network. This guide will walk you through the process of setting up Nagios monitoring using Docker.&lt;/p&gt;
&lt;h2 id="finding-a-docker-image-for-nagios"&gt;Finding a Docker Image for Nagios&lt;a class="anchor ms-1" href="#finding-a-docker-image-for-nagios" aria-label="Permalink: Finding a Docker Image for Nagios"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, we need to find a suitable Docker image for Nagios. The &lt;a href="https://hub.docker.com/r/manios/nagios" target="_blank" rel="noopener noreferrer"&gt;manios/nagios&lt;/a&gt;
image looks like it should do the job.&lt;/p&gt;
&lt;h2 id="running-the-nagios-docker-container"&gt;Running the Nagios Docker Container&lt;a class="anchor ms-1" href="#running-the-nagios-docker-container" aria-label="Permalink: Running the Nagios Docker Container"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The basics of running this container are as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run -d --name nagios -p 8080:80 manios/nagios
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This command will pull the Nagios image from Docker Hub and run it in a container, mapping port 80 in the container to port 8080 on your host machine.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run -d --name nagios &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -v /path-to-nagios/etc/:/opt/nagios/etc/ &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -v /path-to-nagios/var:/opt/nagios/var/ &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -v /path-to-nagios/ssmtp.conf:/etc/ssmtp/ssmtp.conf &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -v /path-to-custom-plugins:/opt/Custom-Nagios-Plugins &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -p 8080:80 &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; manios/nagios
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I prefer running via docker compose, which looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;nagios&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;manios/nagios:latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;container_name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;monitoring_nagios&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;8081&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;./nagios/localhost.cfg:/opt/nagios/etc/objects/localhost.cfg&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;./nagios/windows.cfg:/opt/nagios/etc/objects/windows.cfg&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;nagios_data:/opt/nagios/var/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;NAGIOSADMIN_USER=nagiosadmin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;NAGIOSADMIN_PASS=nagiosadmin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;NAGIOS_TIMEZONE=UTC&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;NAGIOS_WEB_USER=nagiosadmin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;NAGIOS_WEB_PASS=nagiosadmin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="accessing-the-nagios-web-interface"&gt;Accessing the Nagios Web Interface&lt;a class="anchor ms-1" href="#accessing-the-nagios-web-interface" aria-label="Permalink: Accessing the Nagios Web Interface"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once the container is running, you can access the Nagios web interface by navigating to http://localhost:8080 in your web browser. You should see the Nagios login page.&lt;/p&gt;
&lt;h2 id="configuring-nagios"&gt;Configuring Nagios&lt;a class="anchor ms-1" href="#configuring-nagios" aria-label="Permalink: Configuring Nagios"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To configure Nagios, you&amp;rsquo;ll need to edit the configuration files located in the container. You can do this by accessing the container&amp;rsquo;s shell:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker exec -it nagios /bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From here, you can navigate to the Nagios configuration directory and make the necessary changes:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd /opt/nagios/etc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="adding-hosts-and-services"&gt;Adding Hosts and Services&lt;a class="anchor ms-1" href="#adding-hosts-and-services" aria-label="Permalink: Adding Hosts and Services"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To monitor your local network, you&amp;rsquo;ll need to add hosts and services to the Nagios configuration. This involves editing the configuration files and adding each host and service you want to monitor.&lt;/p&gt;
&lt;p&gt;I have added a few extra hosts to the localhost.cfg file to monitor my router, and a few other devices on my network. I have also added a Volume to store the nagios data, so after a restart of the container the data is still there.&lt;/p&gt;
&lt;p&gt;Lets have a look at how hosts and services are defined in the config files.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cfg" data-lang="cfg"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;define host{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;use linux-server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;host_name router&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;alias router&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;parents localhost; Hosts that this host is dependent on &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;address 192.168.2.1; IP Address or DNS name of the host&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cfg" data-lang="cfg"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;define service{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;use local-service,graphed-service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;host_name localhost, router&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;service_description PING&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;check_command check_ping!100.0,20%!500.0,60%&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When making changes to your config files it is useful to check the config is valid. To do this with the docker file you can run the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker exec -it mynagioscontainer bin/nagios -v etc/nagios.cfg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It may have been 10 years since I last looked at Nagios, but the UI hasn&amp;rsquo;t changed much. Host are checked if they are Up or Down, and every Host can have a number of services associated with it and this are checked if they are Up or Down.&lt;/p&gt;
&lt;p&gt;
&lt;img class="img-fluid" alt="Nagios UI" src="https://blog-test.funkysi1701.com/images/nagios.png" loading="lazy"
width="1605" height="702"
/&gt;
&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;a class="anchor ms-1" href="#conclusion" aria-label="Permalink: Conclusion"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;By following these steps, you can set up Nagios monitoring using Docker to keep an eye on your local network. Nagios is a powerful tool for network monitoring, and running it in a Docker container makes it easy to deploy and manage. Happy monitoring!&lt;/p&gt;
&lt;h3 id="related-on-this-blog"&gt;Related on this blog&lt;a class="anchor ms-1" href="#related-on-this-blog" aria-label="Permalink: Related on this blog"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For application metrics and dashboards rather than host ping checks, see &lt;a href="https://blog-test.funkysi1701.com/posts/2025/setting-up-grafana/"&gt;setting up Grafana&lt;/a&gt;
with Prometheus. I also wrote about &lt;a href="https://blog-test.funkysi1701.com/posts/2014/i-love-nagios/"&gt;loving Nagios&lt;/a&gt;
the first time around — the UI has barely moved since.&lt;/p&gt;</description></item></channel></rss>