<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Kılıç's Kooky Computer Kitchen]]></title><description><![CDATA[software carpenter's workshop]]></description><link>https://blog.muhammedkilic.com</link><generator>RSS for Node</generator><lastBuildDate>Wed, 13 May 2026 06:29:33 GMT</lastBuildDate><atom:link href="https://blog.muhammedkilic.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Understanding Dark Patterns in Digital Design]]></title><description><![CDATA[Endorsements (aka "Social Proof")

False Activity Messages: Sites falsely claim high user activity or interest in a product to create urgency.

Deceptive Consumer Testimonials: Using fake endorsements or presenting testimonials without disclosing mat...]]></description><link>https://blog.muhammedkilic.com/understanding-dark-patterns-in-digital-design</link><guid isPermaLink="true">https://blog.muhammedkilic.com/understanding-dark-patterns-in-digital-design</guid><category><![CDATA[dart-patterns]]></category><dc:creator><![CDATA[Muhammed Kılıç]]></dc:creator><pubDate>Wed, 17 Jul 2024 19:37:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1721244966283/2a6672f7-9dd7-42dc-8767-cb76331e237d.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-endorsements-aka-social-proof">Endorsements (aka "Social Proof")</h3>
<ol>
<li><p><strong>False Activity Messages</strong>: Sites falsely claim high user activity or interest in a product to create urgency.</p>
</li>
<li><p><strong>Deceptive Consumer Testimonials</strong>: Using fake endorsements or presenting testimonials without disclosing material information.</p>
</li>
<li><p><strong>Deceptive Celebrity Endorsements</strong>: Falsely attributing testimonials to celebrities.</p>
</li>
<li><p><strong>Parasocial Relationship Pressure</strong>: Leveraging trusted characters, especially those familiar to children, to influence choices.</p>
</li>
</ol>
<h3 id="heading-scarcity">Scarcity</h3>
<ol>
<li><p><strong>False Low Stock Message</strong>: Misleading users by indicating low stock to prompt immediate purchases.</p>
</li>
<li><p><strong>False High Demand Message</strong>: Creating a false sense of urgency by claiming high demand.</p>
</li>
</ol>
<h3 id="heading-urgency">Urgency</h3>
<ol>
<li><p><strong>Baseless Countdown Timer</strong>: Displaying a fake countdown clock to pressure immediate purchases.</p>
</li>
<li><p><strong>False Limited Time Message</strong>: Suggesting offers are time-limited when they are not.</p>
</li>
<li><p><strong>False Discount Claims</strong>: Advertising fake discounts or sales to lure consumers.</p>
</li>
</ol>
<h3 id="heading-obstruction">Obstruction</h3>
<ol>
<li><p><strong>Price Comparison Prevention</strong>: Making it difficult for shoppers to compare prices by bundling items or using inconsistent measures.</p>
</li>
<li><p><strong>Roadblocks to Cancellation</strong>: Designing processes that make it easy to sign up but challenging to cancel.</p>
</li>
<li><p><strong>Immortal Accounts</strong>: Making it hard or impossible to delete an account.</p>
</li>
</ol>
<h3 id="heading-sneaking-or-information-hiding">Sneaking or Information Hiding</h3>
<ol>
<li><p><strong>Sneak-into-Basket</strong>: Automatically adding items to the shopping cart without the user’s consent.</p>
</li>
<li><p><strong>Hidden Information</strong>: Withholding essential information or significant product limitations.</p>
</li>
<li><p><strong>Hidden Costs</strong>: Adding fees or charges that are not initially disclosed.</p>
</li>
<li><p><strong>Drip Pricing</strong>: Advertising a partial price and adding mandatory charges later in the buying process.</p>
</li>
<li><p><strong>Hidden Subscription or Forced Continuity</strong>: Offering a free trial that transitions into a paid subscription without clear consent.</p>
</li>
</ol>
<h3 id="heading-interface-interference">Interface Interference</h3>
<ol>
<li><p><strong>Misdirection</strong>: Designing elements to focus user attention away from critical information.</p>
</li>
<li><p><strong>False Hierarchy or Pressured Upselling</strong>: Using visual prominence to nudge users toward specific choices.</p>
</li>
<li><p><strong>Disguised Ads</strong>: Making advertisements look like unbiased product reviews or independent articles.</p>
</li>
<li><p><strong>Bait and Switch</strong>: Leading users to expect one outcome but delivering another.</p>
</li>
</ol>
<h3 id="heading-coerced-action">Coerced Action</h3>
<ol>
<li><p><strong>Unauthorized Transactions</strong>: Tricking users into paying for goods or services they didn’t intend to buy.</p>
</li>
<li><p><strong>Auto-Play</strong>: Automatically playing additional videos in a disruptive or harmful manner.</p>
</li>
<li><p><strong>Nagging</strong>: Repeatedly and disruptively asking users to take an action.</p>
</li>
<li><p><strong>Forced Registration or Enrollment</strong>: Requiring account creation or information sharing to complete a task.</p>
</li>
<li><p><strong>Pay-to-Play or Grinding</strong>: Advertising free access but then charging for full functionality.</p>
</li>
<li><p><strong>Friend Spam, Social Pyramid Schemes, and Address Book Leeching</strong>: Misusing email addresses or social media permissions for unintended purposes.</p>
</li>
</ol>
<h3 id="heading-asymmetric-choice">Asymmetric Choice</h3>
<ol>
<li><p><strong>Trick Questions</strong>: Using confusing language to steer users towards unwanted actions.</p>
</li>
<li><p><strong>Confirm Shaming</strong>: Shaming users into making certain choices by framing alternatives negatively.</p>
</li>
<li><p><strong>Preselection</strong>: Preselecting options that benefit the company but not the user.</p>
</li>
<li><p><strong>Subverting Privacy Preferences</strong>: Tricking users into sharing more information than intended.</p>
</li>
</ol>
<p>Source: <a target="_blank" href="https://www.ftc.gov/reports/bringing-dark-patterns-light">https://www.ftc.gov/reports/bringing-dark-patterns-light</a></p>
]]></content:encoded></item><item><title><![CDATA[The Power of Secure Coding Practices: Safeguarding MongoDB Against Exploitation]]></title><description><![CDATA[Hello everyone, I need to tell a little story first:
Several months ago I was working on a side project for automating the election results display. I had a quick development process and published the website with Ampt and the database server. My Sec...]]></description><link>https://blog.muhammedkilic.com/the-power-of-secure-coding-practices-safeguarding-mongodb-against-exploitation</link><guid isPermaLink="true">https://blog.muhammedkilic.com/the-power-of-secure-coding-practices-safeguarding-mongodb-against-exploitation</guid><category><![CDATA[MongoDB]]></category><category><![CDATA[Security]]></category><category><![CDATA[NoSQL]]></category><category><![CDATA[injection]]></category><category><![CDATA[mongoose]]></category><dc:creator><![CDATA[Muhammed Kılıç]]></dc:creator><pubDate>Tue, 11 Jul 2023 20:48:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1689104282736/e05a5bd9-322c-42d6-9807-79ae33395e69.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello everyone, I need to tell a little story first:</p>
<p>Several months ago I was working on a side project for automating the election results display. I had a quick development process and published the website with <a target="_blank" href="https://ampt.dev/">Ampt</a> and the database server. My Security Researcher friend Sven immediately sent the URL he exploited the application and I was kind of surprised as I was using default queries nothing very specific but the result was there, he was blocking my application to proceed with data with fun! Thanks, Sven :)</p>
<p>I understood that there are many vulnerabilities out there but even the most common code examples we read, copy and even run out there were not safe enough.</p>
<blockquote>
<p>Kein system ist sicher!</p>
</blockquote>
<p>Before starting I would like to suggest taking a look at <strong>CWE-943: Improper Neutralization of Special Elements in Data Query Logic</strong> to understand what is NoSQL injection and how it related to MongoDB.</p>
<p>You may have read my level-up advice for development environment setup post, here is another database with docker-compose:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">version:</span> <span class="hljs-string">'3'</span>

<span class="hljs-attr">services:</span>
  <span class="hljs-attr">database:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">mongo</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"27017:27017"</span>
</code></pre>
<p>Run MongoDB without authentication, only for experimental purposes, please activate authentication for production!</p>
<p>I will use <a target="_blank" href="https://www.mongodb.com/products/compass">MongoDB Compass GUI</a> to show a little bit about MongoDB queries.</p>
<p>I have a document - not a table in NoSQL we call it a document not the same but closest naming - called <code>users</code>.</p>
<p>This is how it looks like as I am not filtering any data:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1689103641814/1931664d-9c20-448a-ae8d-b7fa5e8547ba.png" alt class="image--center mx-auto" /></p>
<p>I would like to filter Jane Smith with email and the query will be:<br /><code>{ $where: "this.email == 'janesmith@example.com'" }</code>.</p>
<p>So far:</p>
<ul>
<li><p>We know how to write a MongoDB Query.</p>
</li>
<li><p>We know how to filter documents.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1689103662596/be0426ca-abec-4493-ba50-035da6bbe749.png" alt class="image--center mx-auto" /></p>
<p>As you can see from the query there is a comparison and when the expression for the MongoDB operator <code>$where</code> evaluates to <code>true</code> the data will be accessed.</p>
<p>We will be replacing the email address of Jane Smith with: <code>'||'true</code> to escape from the original query and force every <code>$where</code> the operator is to be calculated as <code>true</code>.<br />The first single quote will create an empty string, which forces the email address to be compared to an empty string and will be evaluated as <code>false</code>. We also concatenated Logical OR and <code>'true'</code> where the final expression will fallback to <code>false || true</code>.</p>
<pre><code class="lang-bash">{ <span class="hljs-variable">$where</span>: <span class="hljs-string">"this.email == 'janesmith@example.com'"</span> }
{ <span class="hljs-variable">$where</span>: <span class="hljs-string">"this.email == ''||'true'"</span> }
</code></pre>
<p>When you run the injected email value, you will obtain all data from the <code>sample.users</code> document as shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1689103702709/fc1cafa9-85d3-464e-a8d1-794be6687df8.png" alt class="image--center mx-auto" /></p>
<p>So far I showed how to exploit a basic MongoDB query, you should know that this is not the only way to exploit it. <strong>For this post, I will be focusing on this boolean-based injection payload.</strong></p>
<p>Let's create a MongoDB-Express application to have a real-life example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>);

<span class="hljs-keyword">const</span> app = express();

<span class="hljs-keyword">const</span> mongoURL = <span class="hljs-string">'mongodb://localhost:27017/sample'</span>; 

<span class="hljs-keyword">const</span> userSchema = <span class="hljs-keyword">new</span> mongoose.Schema({
    <span class="hljs-attr">name</span>: <span class="hljs-built_in">String</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-built_in">String</span>,
    <span class="hljs-attr">admin</span>: <span class="hljs-built_in">Boolean</span>
});

<span class="hljs-keyword">const</span> User = mongoose.model(<span class="hljs-string">'User'</span>, userSchema);

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">connectToDatabase</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">await</span> mongoose.connect(mongoURL, {
            <span class="hljs-attr">useNewUrlParser</span>: <span class="hljs-literal">true</span>,
            <span class="hljs-attr">useUnifiedTopology</span>: <span class="hljs-literal">true</span>
        });
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Connected to MongoDB'</span>);
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Failed to connect to MongoDB:'</span>, err);
        process.exit(<span class="hljs-number">1</span>);
    }
}

app.get(<span class="hljs-string">'/'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    res.send(<span class="hljs-string">'Running MongoDB with Node.js'</span>);
});

app.get(<span class="hljs-string">'/users'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
    <span class="hljs-keyword">await</span> connectToDatabase();

    <span class="hljs-keyword">const</span> email = req.query.email;

    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> query = { <span class="hljs-attr">$where</span>: <span class="hljs-string">`this.email == '<span class="hljs-subst">${email}</span>'`</span> };
        <span class="hljs-keyword">const</span> users = <span class="hljs-keyword">await</span> User.find(query);
        <span class="hljs-keyword">if</span> ( users.length === <span class="hljs-number">0</span> ) {
            res.status(<span class="hljs-number">404</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">'User not found'</span> });
            <span class="hljs-keyword">return</span>;
        }
        res.status(<span class="hljs-number">200</span>).json(users);
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Failed to retrieve users:'</span>, err.message);
        <span class="hljs-built_in">console</span>.group(<span class="hljs-string">'Stack trace'</span>);
        <span class="hljs-built_in">console</span>.error(err);
        <span class="hljs-built_in">console</span>.groupEnd();
        res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">'Internal server error'</span> });
    }
});

app.listen(<span class="hljs-number">3000</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Server is running on port 3000'</span>);
});
</code></pre>
<p>For this application we will have an endpoint:</p>
<ul>
<li><p><a target="_blank" href="http://localhost:3000/users?email=janesmith@example.com">http://localhost:3000/users?email=janesmith@example.com</a> will return "User not found" error.</p>
</li>
<li><p><a target="_blank" href="http://localhost:3000/users?email=%27%7C%7C%27true">http://localhost:3000/users?email=%27%7C%7C%27true</a> will return all of the data from users document</p>
</li>
</ul>
<p>The decoded query value <code>%27%7C%7C%27true</code> is equal to <code>'||'true</code>. Browsers will decode automatically.</p>
<p>Let's focus on the code:<br />We are assigning email variable with this line:<br /><code>const email = req.query.email;</code> Here is the first mistake most developers do. We are getting data from outside of the application, users, customers, frontend whatever you call it. We should sanitize the data to be sure it is ready to be used.<br />There are some libraries to sanitize the data, for Express we can use <a target="_blank" href="https://www.npmjs.com/package/mongo-sanitize">mongo-sanitize</a>. Basically, we need to escape from the special characters before executing database queries. If we sanitize the boolean injection payload the query and the result will be like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1689107790062/4dc66c67-7610-45f4-bd4e-727c0e97f313.png" alt class="image--center mx-auto" /></p>
<p>Here is another suggestion for this case lets take a look at query construction:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> query = { <span class="hljs-attr">$where</span>: <span class="hljs-string">`this.email == '<span class="hljs-subst">${email}</span>'`</span> };
</code></pre>
<p>We are using single quotes for email value and it results in queries below:</p>
<pre><code class="lang-bash">{ <span class="hljs-variable">$where</span>: <span class="hljs-string">"this.email == 'janesmith@example.com'"</span> }
{ <span class="hljs-variable">$where</span>: <span class="hljs-string">"this.email == ''||'true'"</span> }
</code></pre>
<p>However, we could escape by using backticks to avoid injection payloads:</p>
<pre><code class="lang-bash">{ <span class="hljs-variable">$where</span>: <span class="hljs-string">"this.email == `janesmith@example.com`"</span> }
{ <span class="hljs-variable">$where</span>: <span class="hljs-string">"this.email == `'||'true`"</span> }
</code></pre>
<p>To conclude we are sanitizing inputs and using default query methods advised to avoid injections.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> email = sanitize(req.query.email); <span class="hljs-comment">// Sanitize input to avoid NoSQL injection</span>
<span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> users = <span class="hljs-keyword">await</span> User.find({ email }); <span class="hljs-comment">// use default query options to avoid NoSQL injection</span>
    <span class="hljs-keyword">if</span> ( users.length === <span class="hljs-number">0</span> ) {
        res.status(<span class="hljs-number">404</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">'User not found'</span> });
        <span class="hljs-keyword">return</span>;
    }
    res.status(<span class="hljs-number">200</span>).json(users);
} <span class="hljs-keyword">catch</span> (err) {
</code></pre>
<p>I wanted to draw attention to the importance of writing secure code, as it is susceptible to vulnerabilities. Vulnerabilities arise from the improper neutralization of special elements in data query logic. Attackers can exploit this weakness to manipulate queries, modify selection criteria, append unauthorized commands, or obtain unintended results. To mitigate the risk, developers must focus on implementing rigorous input validation and sanitization techniques for No/SQL Injections. By adopting secure coding practices, such as parameterized queries and proper input handling, developers can fortify MongoDB applications and protect against NoSQL injection attacks.</p>
<p>Thanks for reading so far! Thanks, Sven for exploiting!</p>
]]></content:encoded></item><item><title><![CDATA[Level Up Your Development Experience with Docker Compose]]></title><description><![CDATA[🦾
Let me know if you have feedback!


Docker has revolutionized the way developers build, ship, and run applications. It provides a lightweight and portable environment for isolating applications and their dependencies. One of the powerful tools in ...]]></description><link>https://blog.muhammedkilic.com/level-up-your-development-experience-with-docker-compose</link><guid isPermaLink="true">https://blog.muhammedkilic.com/level-up-your-development-experience-with-docker-compose</guid><category><![CDATA[Docker]]></category><category><![CDATA[Docker compose]]></category><category><![CDATA[development]]></category><category><![CDATA[PostgreSQL]]></category><category><![CDATA[Redis]]></category><dc:creator><![CDATA[Muhammed Kılıç]]></dc:creator><pubDate>Mon, 10 Jul 2023 11:39:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1689142906896/4f2b6320-4961-48ce-8e93-e91811e56e16.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div data-node-type="callout">
<div data-node-type="callout-emoji">🦾</div>
<div data-node-type="callout-text">Let me know if you have feedback!</div>
</div>

<p>Docker has revolutionized the way developers build, ship, and run applications. It provides a lightweight and portable environment for isolating applications and their dependencies. One of the powerful tools in the Docker ecosystem is Docker Compose, which allows you to define and manage multi-container applications. In this blog post, we will explore how to use Docker Compose for development, focusing on a simple example with a PostgreSQL database and a Redis cache.</p>
<p>I have been working with these tricks to avoid problems like slow connection to remote databases, clean install, forgetting the passwords etc. Let's start!</p>
<p>Make sure you have Docker and Docker Compose installed on your machine.</p>
<pre><code class="lang-bash">$ docker -v
&gt; Docker version 24.0.2, build cb74dfcd85 
$ docker-compose -v
&gt; Docker Compose version v2.12.1
</code></pre>
<p>Docker Compose comes bundled with Docker Desktop for Windows and macOS, while Linux users can install it separately. Once you have everything set up, create a new directory for your project and navigate into it.</p>
<p>Defining the Docker Compose File: In your project directory, create a file called <code>docker-compose.yml</code> and open it in a text editor. This file will contain the configuration for your Docker Compose environment. Start by specifying the version at the top of the file:</p>
<p>Let's define the services we want to run using Docker Compose. In our example, we'll have two services: a PostgreSQL database and a Redis cache. Add the following code to your <code>docker-compose.yml</code> file:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">version:</span> <span class="hljs-string">'3'</span>

<span class="hljs-attr">services:</span>
  <span class="hljs-attr">db:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">postgres:latest</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">always</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">./postgres-data:/var/lib/postgresql/data</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"5432:5432"</span>
    <span class="hljs-attr">environment:</span>
        <span class="hljs-attr">POSTGRES_USER:</span> <span class="hljs-string">postgres</span>
        <span class="hljs-attr">POSTGRES_PASSWORD:</span> <span class="hljs-string">postgres</span>
        <span class="hljs-attr">POSTGRES_DB:</span> <span class="hljs-string">postgres</span>

  <span class="hljs-attr">redis:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">redis:latest</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">always</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"6379:6379"</span>
</code></pre>
<p>Explanation:</p>
<ul>
<li><p>The <code>db</code> service is based on the latest PostgreSQL image. We specify that it should always restart and mount a local directory (<code>./postgres-data</code>) as the data volume for persistent storage.</p>
</li>
<li><p>Port <code>5432</code> on the host machine is mapped to port <code>5432</code> on the <code>db</code> service container, allowing us to access the PostgreSQL database externally.</p>
</li>
<li><p>Environment variables are set to configure the PostgreSQL instance.</p>
</li>
<li><p>The <code>redis</code> service is based on the latest Redis image. It also restarts automatically, and port <code>6379</code> on the host machine is mapped to port <code>6379</code> on the <code>redis</code> service container.</p>
</li>
</ul>
<p>Save the <code>docker-compose.yml</code> file and return to your terminal. To start the defined services, use the following command in your project directory:</p>
<pre><code class="lang-bash">$ docker-compose up
$ <span class="hljs-comment"># docker-compose up --build -d</span>
</code></pre>
<p>Docker Compose will download the necessary images (if not already present) and start the containers. You'll see the output from each service, and you can monitor their logs in real-time.</p>
<p>Accessing the Services: With the services up and running, you can access them from your development environment. For example, you can connect to the PostgreSQL database using your preferred database client and the following connection details:</p>
<ul>
<li><p>Host: <a target="_blank" href="http://localhost"><code>localhost</code></a></p>
</li>
<li><p>Port: <code>5432</code></p>
</li>
<li><p>Username: <code>postgres</code></p>
</li>
<li><p>Password: <code>postgres</code></p>
</li>
</ul>
<p>Similarly, you can connect to the Redis cache using <a target="_blank" href="http://localhost"><code>localhost</code></a> and port <code>6379</code>.</p>
<p>To verify connectivity, you can use the following URLs:</p>
<ul>
<li><p>Redis: <code>redis://localhost:6379</code></p>
</li>
<li><p>PostgreSQL: <code>postgresql://postgres:</code><a target="_blank" href="mailto:postgres@localhost:5432"><code>postgres@localhost:5432/postgres</code></a></p>
</li>
</ul>
<p>These URLs can be directly used in your application code or database clients to establish connections with the Redis and PostgreSQL databases. Make sure that the Docker Compose services are running, and then test the connections. If you encounter any connection errors, double-check the URLs and ensure that the services are running correctly. Verifying connectivity at this stage will help ensure smooth development without any connectivity issues.</p>
<p>Docker Compose is a powerful tool for managing multi-container applications in a development environment. It simplifies the setup and configuration of complex application stacks, allowing developers to focus on building their applications rather than managing dependencies. In this blog post, we explored a simple example with a PostgreSQL database and a Redis cache, but Docker Compose can be used for a wide range of application architectures.</p>
<p>Take care of your health!</p>
]]></content:encoded></item><item><title><![CDATA[hello hashnoders!]]></title><description><![CDATA[this is my trial for not leaving my blog page empty. i am a human work with devices. devices are fun human are less... 
anyway hope to continue on this blog not as other ones in my past, sorry.]]></description><link>https://blog.muhammedkilic.com/hello-hashnoders</link><guid isPermaLink="true">https://blog.muhammedkilic.com/hello-hashnoders</guid><dc:creator><![CDATA[Muhammed Kılıç]]></dc:creator><pubDate>Thu, 20 Aug 2020 19:17:31 GMT</pubDate><content:encoded><![CDATA[<p>this is my trial for not leaving my blog page empty. i am a human work with devices. devices are fun human are less... </p>
<p>anyway hope to continue on this blog not as other ones in my past, sorry.</p>
]]></content:encoded></item></channel></rss>