<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>api - Hard Wired</title>
	<atom:link href="https://www.hardwired.dev/tag/api/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.hardwired.dev</link>
	<description></description>
	<lastBuildDate>Wed, 11 Mar 2026 15:26:11 +0000</lastBuildDate>
	<language>cs</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.hardwired.dev/wp-content/uploads/2022/10/android-chrome-256x256-1-150x150.png</url>
	<title>api - Hard Wired</title>
	<link>https://www.hardwired.dev</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Průvodce modely Claude od Anthropic</title>
		<link>https://www.hardwired.dev/2026/03/11/pruvodce-modely-claude-od-anthropic/</link>
		
		<dc:creator><![CDATA[Valentino Hesse OK2HSS]]></dc:creator>
		<pubDate>Wed, 11 Mar 2026 15:26:11 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[agentic AI]]></category>
		<category><![CDATA[AI asistent]]></category>
		<category><![CDATA[AI models comparison]]></category>
		<category><![CDATA[Anthropic]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[API pricing]]></category>
		<category><![CDATA[artificial intelligence]]></category>
		<category><![CDATA[chatbot]]></category>
		<category><![CDATA[claude]]></category>
		<category><![CDATA[claude ai]]></category>
		<category><![CDATA[coding assistant]]></category>
		<category><![CDATA[extended thinking]]></category>
		<category><![CDATA[generativní AI]]></category>
		<category><![CDATA[Haiku]]></category>
		<category><![CDATA[jazykové modely]]></category>
		<category><![CDATA[kódování]]></category>
		<category><![CDATA[kontextové okno]]></category>
		<category><![CDATA[large language models]]></category>
		<category><![CDATA[LLM]]></category>
		<category><![CDATA[machine learning]]></category>
		<category><![CDATA[neural networks]]></category>
		<category><![CDATA[neuronové sítě]]></category>
		<category><![CDATA[Opus]]></category>
		<category><![CDATA[programování]]></category>
		<category><![CDATA[prompt engineering]]></category>
		<category><![CDATA[Sonnet]]></category>
		<category><![CDATA[strojové učení]]></category>
		<category><![CDATA[tokenizace]]></category>
		<category><![CDATA[umela inteligence]]></category>
		<guid isPermaLink="false">https://www.hardwired.dev/?p=2968</guid>

					<description><![CDATA[<p>Průvodce modely Claude od Anthropic Úvod Anthropic je americká firma, která se zabývá vývojem bezpečné AI - jejich hlavní produkt &#62;&#62;&#62;</p>
<p>The post <a href="https://www.hardwired.dev/2026/03/11/pruvodce-modely-claude-od-anthropic/">Průvodce modely Claude od Anthropic</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><h1>Průvodce modely Claude od Anthropic</h1>
<h2>Úvod</h2>
<p>Anthropic je americká firma, která se zabývá vývojem bezpečné AI - jejich hlavní produkt je rodina jazykových modelů Claude, v současnosti jedny z nejpokročilejších AI asistentů na trhu, které mají tři hlavní úrovně: <strong>Opus</strong>, <strong>Sonnet</strong> a <strong>Haiku</strong>. Když jsem poprvé začal s těmito modely pracovat, upřímně jsem nevěděl který kdy použít - všechny vypadaly podobně, ale rozdíly v kvalitě výstupu a ceně byly obrovské. V tomhle článku si projdeme co který model umí, kdy ho použít a proč, a sdílím zkušenosti z reálných projektů kde jsem každý z nich testoval.</p>
<hr />
<h2>Architektura rodiny Claude</h2>
<p>Anthropic postavil třístupňovou hierarchii modelů, kde každá úroveň má svoje místo:</p>
<table>
<thead>
<tr>
<th>Model</th>
<th>Charakteristika</th>
<th>Primární využití</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Opus</strong></td>
<td>Nejinteligentnější, nejhlubší uvažování</td>
<td>Komplexní analýzy, výzkum, náročné programování</td>
</tr>
<tr>
<td><strong>Sonnet</strong></td>
<td>Vyvážený výkon a rychlost</td>
<td>Každodenní práce, kódování, většina úloh</td>
</tr>
<tr>
<td><strong>Haiku</strong></td>
<td>Nejrychlejší, nejlevnější</td>
<td>Real-time aplikace, vysoký objem dotazů</td>
</tr>
</tbody>
</table>
<p>Všechny modely používají Constitutional AI framework pro bezpečnost a mají kontextové okno 200 000 tokenů (zhruba 150 000 slov), což v praxi znamená že můžeš nahrát celou kódovou bázi menšího projektu nebo technickou knihu a model si pamatuje všechno. Novější verze Opus a Sonnet nabízejí experimentální podporu až 1 milion tokenů - zkoušel jsem to s kompletní dokumentací ESP-IDF frameworku a fungovalo to překvapivě dobře, i když latence byla znatelně vyšší.</p>
<hr />
<h2>Claude Opus — hluboký myslitel</h2>
<h3>Co je Opus?</h3>
<p>Opus je top tier model od Anthropic - navržený pro úlohy kde potřebuješ hluboké analytické uvažování, komplexní vícekrokové plánování, pokročilé programování a refaktoring, nebo práci s rozsáhlými kontexty jako jsou celé knihy nebo velké kódové báze. Když jsem poprvé testoval Opus na code review komplexní Flask aplikace s asynchronními tasky a Celery workers, byl jsem fascinovaný tím, jak model dokázal propojit souvislosti mezi moduly které byly od sebe vzdálené stovky řádků kódu a identifikovat potenciální race condition, kterou jsem já sám přehlédl.</p>
<h3>Kdy použít Opus?</h3>
<p><strong>Ideální scénáře:</strong></p>
<ol>
<li><strong>Code review před nasazením</strong> — Opus zachytí subtilní chyby jako memory leaky, async bugy nebo chybějící dispose volání, které ostatní modely přehlédnou</li>
<li><strong>Architektonická rozhodnutí</strong> — Při návrhu systémové architektury nebo rozsáhlém refaktoringu</li>
<li><strong>Výzkum a analýza</strong> — Sumarizace celých knih, analýza právních dokumentů, finanční modelování</li>
<li><strong>Agentické workflow</strong> — Dlouhodobé autonomní úlohy vyžadující vícekrokové uvažování</li>
</ol>
<h3>Praktický příklad</h3>
<pre><code>Scénář: Máš komplexní Flask aplikaci s 50+ soubory a potřebuješ identifikovat 
bezpečnostní zranitelnosti.

Proč Opus: Model dokáže udržet kontext celé aplikace, propojit souvislosti mezi 
moduly a identifikovat zranitelnosti typu race condition nebo injection attacks, 
které vyžadují pochopení toku dat napříč celým systémem.</code></pre>
<h3>Cena</h3>
<table>
<thead>
<tr>
<th>Typ</th>
<th>Cena za milion tokenů</th>
</tr>
</thead>
<tbody>
<tr>
<td>Vstupní tokeny</td>
<td>$5</td>
</tr>
<tr>
<td>Výstupní tokeny</td>
<td>$25</td>
</tr>
</tbody>
</table>
<p>Opus 4.5 přinesl výrazné zlevnění oproti předchozím verzím (Opus 4/4.1 stál $15/$75), což zpřístupnilo prémiovou inteligenci širšímu spektru uživatelů - upřímně, při těch starých cenách jsem Opus používal jen na kritické review před nasazením do produkce, protože každý delší prompt stál dost peněz. Teď s novými cenami je to mnohem dostupnější, i když pořád ne na každodenní použití pokud máš omezený budget.</p>
<hr />
<h2>Claude Sonnet — spolehlivý kolega</h2>
<h3>Co je Sonnet?</h3>
<p>Sonnet je vyvážený model - kombinuje vysokou inteligenci s rozumnou rychlostí a cenou, což z něj dělá ideální volbu pro většinu každodenní práce. Většina vývojářů tráví s tímhle modelem nejvíc času, a já nejsem výjimka - odhadem 80 % mých promptů jde na Sonnet, protože pro běžné programování, refaktoring nebo psaní dokumentace je naprosto dostačující a odpovídá rychle.</p>
<h3>Kdy použít Sonnet?</h3>
<p><strong>Ideální scénáře:</strong></p>
<ol>
<li><strong>Každodenní programování</strong> — Vývoj funkcí, práce s více soubory, správa stavu, připojení k API</li>
<li><strong>Analýza a reporting</strong> — Strukturované analýzy, Q&amp;A s dokumenty, vytváření reportů</li>
<li><strong>Kreativní úlohy</strong> — Psaní obsahu, copywriting, technická dokumentace</li>
<li><strong>Orchestrace agentů</strong> — Sonnet vytvoří plán a rozdělí úkoly pro Haiku instance</li>
</ol>
<h3>Praktický příklad</h3>
<pre><code>Scénář: Vyvíjíš React aplikaci s Tailwind CSS a potřebuješ implementovat
autentizaci s Firebase.

Proč Sonnet: Model zvládne multi-file logiku, správu stavu (Riverpod, Redux),
připojení k Firebase a generuje čistý, použitelný kód. Má vynikající výkon
v oblasti frontend/UI vývoje a generuje „pixel-perfect layouts&quot;.

Osobní zkušenost: Když jsem dělal redesign jednoho projektu s Flutter a Material 3,
Sonnet mi vygeneroval kompletní theme configuration včetně custom color schemes
a typography - kód fungoval na první pokus, což mě docela překvapilo protože
Material 3 API je dost komplexní a čekal jsem že budu muset něco ladit.</code></pre>
<h3>Cena</h3>
<table>
<thead>
<tr>
<th>Typ</th>
<th>Cena za milion tokenů</th>
</tr>
</thead>
<tbody>
<tr>
<td>Vstupní tokeny</td>
<td>$3</td>
</tr>
<tr>
<td>Výstupní tokeny</td>
<td>$15</td>
</tr>
</tbody>
</table>
<p>Sonnet nabízí výkon blížící se Opusu za zlomek ceny, což z něj dělá optimální volbu pro 90 % produkčních úloh - a tady je důležité si uvědomit že rozdíl mezi Sonnetem a Opusem není vždycky tak velký jak by se podle ceny mohlo zdát, takže pokud nejdeš do opravdu komplexních analýz nebo kritického code review, Sonnet ti bude stačit.</p>
<hr />
<h2>Claude Haiku — rychlý sprinter</h2>
<h3>Co je Haiku?</h3>
<p>Haiku je nejrychlejší a nejlevnější model v rodině Claude - optimalizovaný pro minimální latenci (odpovědi pod sekundu), vysoký objem dotazů a nákladovou efektivitu. Upřímně, nejdřív jsem Haiku podceňoval a myslel si že je to jen &quot;levná verze&quot; pro lidi co chtějí ušetřit, ale když jsem ho začal používat na rychlé prototypování UI komponent, zjistil jsem že pro tento konkrétní use case je vlastně lepší než Sonnet - odpovídá skoro okamžitě a pro jednoduchý layout kód je kvalita naprosto dostačující.</p>
<h3>Kdy použít Haiku?</h3>
<p><strong>Ideální scénáře:</strong></p>
<ol>
<li><strong>Chatboti a zákaznická podpora</strong> — Real-time odpovědi bez čekání</li>
<li><strong>UI prototypování</strong> — Rychlé generování layoutů a komponent</li>
<li><strong>Klasifikace a moderace obsahu</strong> — Vysokoobjemové úlohy</li>
<li><strong>Paralelní provádění subtasků</strong> — V orchestrovaném workflow s Sonnetem</li>
</ol>
<h3>Praktický příklad</h3>
<pre><code>Scénář: Potřebuješ rychle vytvořit Flutter screen s Material 3 designem.

Proč Haiku: Model vygeneruje layout téměř okamžitě. Pro brainstorming a rychlé
prototypy je ideální volbou. Ale pozor — v delších sessions „ztrácí nit&quot;
a není vhodný pro komplexní logické stavby.

Osobní zkušenost: Zkoušel jsem s Haiku dělat složitější state management
s Riverpod providers a po třech čtyřech iteracích začal generovat kód který
nedával smysl - zapomínal na kontext z předchozích promptů a navrhoval řešení
která byla v rozporu s tím co jsme dělali předtím. Pro jednoduché úlohy super,
ale na komplexní logiku radši Sonnet.</code></pre>
<h3>Cena</h3>
<table>
<thead>
<tr>
<th>Typ</th>
<th>Cena za milion tokenů</th>
</tr>
</thead>
<tbody>
<tr>
<td>Vstupní tokeny</td>
<td>$1</td>
</tr>
<tr>
<td>Výstupní tokeny</td>
<td>$5</td>
</tr>
</tbody>
</table>
<p>Haiku je 5× levnější než Opus na vstupních tokenech, což z něj dělá ekonomickou volbu pro vysokoobjemové scénáře - pokud děláš chatbota nebo zákaznickou podporu kde potřebuješ zpracovat tisíce dotazů denně, rozdíl v ceně mezi Haiku a Sonnetem se rychle nasčítá na stovky dolarů měsíčně.</p>
<hr />
<h2>Srovnávací tabulka modelů</h2>
<table>
<thead>
<tr>
<th>Vlastnost</th>
<th>Opus 4.5</th>
<th>Sonnet 4.5</th>
<th>Haiku 4.5</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Inteligence</strong></td>
<td>Nejvyšší</td>
<td>Vysoká</td>
<td>Dobrá</td>
</tr>
<tr>
<td><strong>Rychlost</strong></td>
<td>Pomalejší</td>
<td>Střední</td>
<td>Nejrychlejší</td>
</tr>
<tr>
<td><strong>Cena (vstup/výstup)</strong></td>
<td>$5/$25</td>
<td>$3/$15</td>
<td>$1/$5</td>
</tr>
<tr>
<td><strong>Kontextové okno</strong></td>
<td>200K (1M beta)</td>
<td>200K (1M beta)</td>
<td>200K</td>
</tr>
<tr>
<td><strong>Max. výstup</strong></td>
<td>64K tokenů</td>
<td>64K tokenů</td>
<td>32K tokenů</td>
</tr>
<tr>
<td><strong>Extended Thinking</strong></td>
<td>✓</td>
<td>✓</td>
<td>✓</td>
</tr>
<tr>
<td><strong>SWE-bench skóre</strong></td>
<td>80.9%</td>
<td>77.2%</td>
<td>73.3%</td>
</tr>
</tbody>
</table>
<hr />
<h2>Orchestrační workflow — jak modely kombinovat</h2>
<p>Když pracuješ na větším projektu, dává smysl kombinovat modely podle jejich silných stránek - tohle je něco co jsem se naučil až po pár měsících práce s Claude, protože na začátku jsem používal jen Sonnet na všechno a nevěděl jsem že můžu ušetřit čas i peníze tím že rozdělím úlohy mezi modely strategicky.</p>
<h3>Fáze 1: Plánování (Sonnet)</h3>
<p>Sonnet analyzuje požadavky, navrhuje architekturu a rozděluje úkoly na paralelizovatelné podúlohy.</p>
<h3>Fáze 2: Implementace (Haiku)</h3>
<p>Více instancí Haiku provádí subtasky paralelně — scaffolding, komponenty, API integrace.</p>
<h3>Fáze 3: Review (Opus)</h3>
<p>Před mergem provede Opus hlubokou revizi — zachytí async bugy, memory leaky a subtilní logické chyby.</p>
<pre><code>Příklad z praxe:

Developer pracuje na mobilní aplikaci:
1. Používá Haiku pro rychlé UI prototypy
2. Přepne na Sonnet pro implementaci business logiky
3. Před releasem nechá Opus udělat finální code review

Výsledek: Opus odhalil rebuild issues a chybějící disposes,
které Haiku i Sonnet přehlédly.

Moje zkušenost: Přesně tenhle workflow jsem použil na jednom Flutter projektu
kde jsem dělal aplikaci pro správu IoT zařízení. Haiku mi vygeneroval asi 15
různých screen layoutů za pár minut, Sonnet implementoval komunikaci s MQTT
brokerem a state management, a Opus pak při finálním review našel memory leak
v subscription handleru který by v produkci způsobil problémy - model si všiml
že StreamSubscription není správně disposed při dispose() widgetu, což by
vedlo k postupnému nárůstu paměti. Tohle by Sonnet pravděpodobně přehlédl.</code></pre>
<hr />
<h2>Rozhodovací strom: Který model zvolit?</h2>
<pre><code>START
  │
  ├── Je úloha časově kritická (real-time)?
  │     └── ANO → HAIKU
  │
  ├── Je to rutinní práce (coding, analýza, psaní)?
  │     └── ANO → SONNET
  │
  ├── Vyžaduje hluboké uvažování nebo rozsáhlý kontext?
  │     └── ANO → OPUS
  │
  ├── Je to finální review před nasazením?
  │     └── ANO → OPUS
  │
  └── Nejste si jistí?
        └── Začněte se SONNET, eskalujte na OPUS při potřebě</code></pre>
<hr />
<h2>Cenové předplatné pro běžné uživatele</h2>
<p>Pro ty, kteří nepoužívají API, nabízí Anthropic předplatné:</p>
<table>
<thead>
<tr>
<th>Plán</th>
<th>Cena</th>
<th>Co zahrnuje</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Free</strong></td>
<td>$0</td>
<td>Základní přístup k Haiku, omezené využití</td>
</tr>
<tr>
<td><strong>Pro</strong></td>
<td>$20/měsíc</td>
<td>Přístup k Opus i Sonnet, vyšší limity, Claude Code</td>
</tr>
<tr>
<td><strong>Max</strong></td>
<td>$100-200/měsíc</td>
<td>Výrazně vyšší limity, prioritní přístup</td>
</tr>
</tbody>
</table>
<hr />
<h2>Praktické tipy pro optimalizaci nákladů</h2>
<h3>1. Začni s Haiku, eskaluj nahoru</h3>
<p>Pro většinu dotazů postačí Haiku - na Sonnet nebo Opus přepni pouze pro složitější úlohy, což ti ušetří peníze a zároveň nezpomalí workflow, protože Haiku odpovídá tak rychle že rozdíl v latenci je znatelný.</p>
<h3>2. Využij Prompt Caching</h3>
<p>Při opakovaném dotazování na stejný kontext (např. velký dokument) snížíš náklady až o 90 % - tohle je obrovská úspora pokud pracuješ s rozsáhlou kódovou bází nebo dokumentací, protože model si cachuje kontext a při dalších dotazech ho nemusí znovu zpracovávat. Zkoušel jsem to s dokumentací k ESP-IDF a rozdíl v ceně byl dramatický - první prompt stál normálně, ale následující dotazy byly skoro zadarmo.</p>
<h3>3. Batch API pro neurgentní úlohy</h3>
<p>Asynchronní zpracování přes Batch API poskytuje 50% slevu na tokeny.</p>
<h3>4. Optimalizuj prompty</h3>
<p>Každý token stojí peníze. Odstraň zbytečný kontext a buď konkrétní.</p>
<hr />
<h2>Závěr</h2>
<p>Každý model v rodině Claude má svoje místo:</p>
<ul>
<li><strong>Opus</strong> je senior architekt — pomalejší, ale nejspolehlivější pro kritické rozhodnutí a hluboké analýzy</li>
<li><strong>Sonnet</strong> je spolehlivý kolega — zvládne 90 % každodenní práce kvalitně a efektivně, což z něj dělá můj go-to model</li>
<li><strong>Haiku</strong> je rychlý junior — ideální pro opakované úlohy a prototypování, překvapivě schopný pokud víš jak ho použít</li>
</ul>
<p>Nejde o to používat jeden model na všechno. Jde o to strategicky kombinovat jejich silné stránky podle toho, co zrovna potřebuješ - a tohle pochopení přišlo až s praxí, protože na začátku jsem dělal chybu že jsem používal Sonnet i na úlohy kde by Haiku stačil, nebo naopak jsem se snažil ušetřit a používal Sonnet na code review kde by Opus odvedl mnohem lepší práci. Teď po několika měsících práce s těmito modely mám docela dobrý cit kdy který použít, a doufám že tento článek ti pomůže zkrátit tu learning curve.</p>
<hr />
<h2>Zdroje a další čtení</h2>
<ul>
<li><a href="https://docs.anthropic.com">Anthropic dokumentace</a></li>
<li><a href="https://claude.ai">Claude.ai</a></li>
<li><a href="https://claude.com/pricing">API cenový přehled</a></li>
</ul>
<hr />
<p><em>Pro opravu diakritiky a překlepů byl použit model Claude Sonnet 4.5.</em></p>
<p><em>Článek aktualizován: březen 2026</em></p>

<div class="twitter-share"><a href="https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.hardwired.dev%2F2026%2F03%2F11%2Fpruvodce-modely-claude-od-anthropic%2F&#038;via=hessevalentino&#038;related=hessevalentino%3AValentino%20Hesse%20OK2HSS" class="twitter-share-button">Tweet</a></div><p>The post <a href="https://www.hardwired.dev/2026/03/11/pruvodce-modely-claude-od-anthropic/">Průvodce modely Claude od Anthropic</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>NestJS Chapter 01 &#8211; New Project</title>
		<link>https://www.hardwired.dev/2024/06/09/nestjs-chapter-01-new-project/</link>
		
		<dc:creator><![CDATA[John Doe]]></dc:creator>
		<pubDate>Sun, 09 Jun 2024 19:09:38 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[crud]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[endpoint]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[nestjs]]></category>
		<category><![CDATA[nodejs]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[RESTfull]]></category>
		<category><![CDATA[typescript]]></category>
		<guid isPermaLink="false">https://www.hardwired.dev/?p=2235</guid>

					<description><![CDATA[<p>When you use an app, whether it's a web app or a desktop app, that communicates with a remote server &#62;&#62;&#62;</p>
<p>The post <a href="https://www.hardwired.dev/2024/06/09/nestjs-chapter-01-new-project/">NestJS Chapter 01 – New Project</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>When you use an app, whether it's a web app or a desktop app, that communicates with a remote server over the internet, you can be 99% sure there is an API server involved. API servers are the hidden part of the application where almost all the magic happens. One option for creating APIs is <a href="https://docs.nestjs.com/">NestJS</a>, and we will explore it a little bit.</p>
<p><strong>Key Benefits of NestJS:</strong></p>
<ul>
<li><strong>Scalability</strong>: NestJS is built with scalability in mind, making it easy to manage large-scale applications. Its modular architecture allows developers to split their applications into small, reusable modules.</li>
<li><strong>TypeScript Support</strong>: As a framework built on top of TypeScript, NestJS offers all the benefits of TypeScript, including type safety, improved code readability, and maintainability.</li>
<li><strong>Extensive Ecosystem</strong>: NestJS has a rich ecosystem of libraries and tools, which simplifies the development process. It integrates seamlessly with other popular libraries and frameworks like <a href="https://expressjs.com/en/guide/routing.html">Express</a>, <a href="https://fastify.dev/docs/latest/">Fastify</a>, and more.</li>
<li><strong>Ease of Use</strong>: The framework is designed to be developer-friendly, with a well-documented API and a robust CLI that helps in generating boilerplate code, thereby reducing development time.</li>
<li><strong>Dependency Injection</strong>: NestJS uses a powerful dependency injection system, which makes it easier to manage dependencies and promotes better code organization and testability.</li>
</ul>
<blockquote>
<p><strong>Disclaimer:</strong> This article is not primarily intended for people who are new to programming. It is written with the expectation of some experience in programming. To be honest, my motivation for writing this article is to compile my NestJS developer notes, and I've chosen to present them in article form. It will not explain NestJS in detail, nor its architecture. Instead, it will focus on solving specific problems I have encountered. I hope you find it useful. </p>
</blockquote>
<p>In Chapter 1, we will install NestJS and bring the API server to life.</p>
<p>Make sure you are using the latest LTS version of <a href="https://nodejs.org/en">NodeJS</a>.</p>
<p>For project creation and management, we will use <a href="https://docs.nestjs.com/cli/overview">@nestjs/cli</a>. The easiest way is to install it globally.</p>
<pre><code class="language-shell">npm i -g @nestjs/cli</code></pre>
<p>Then, in your projects folder, simply use the <code>nest</code> command to create a new project.</p>
<pre><code class="language-shell">nest new hardwired-nestjs-api-chapter-01</code></pre>
<p>You will be asked which package manager you want to use. I use <code>npm</code>.</p>
<p>When it is done, just delete the <code>.spec.ts</code> files from the <code>src</code> folder. We don't care about tests right now. A bunch of things are already set up, like <code>prettier</code>, <code>eslint</code>, and <code>TypeScript</code> configuration. Useful scripts are prepared in <code>package.json</code>.</p>
<pre><code class="language-json">&quot;scripts&quot;: {
    &quot;build&quot;: &quot;nest build&quot;,
    &quot;format&quot;: &quot;prettier --write \&quot;src/**/*.ts\&quot; \&quot;test/**/*.ts\&quot;&quot;,
    &quot;start&quot;: &quot;nest start&quot;,
    &quot;start:dev&quot;: &quot;nest start --watch&quot;,
    &quot;start:debug&quot;: &quot;nest start --debug --watch&quot;,
    &quot;start:prod&quot;: &quot;node dist/main&quot;,
    &quot;lint&quot;: &quot;eslint \&quot;{src,apps,libs,test}/**/*.ts\&quot; --fix&quot;,
    &quot;test&quot;: &quot;jest&quot;,
    &quot;test:watch&quot;: &quot;jest --watch&quot;,
    &quot;test:cov&quot;: &quot;jest --coverage&quot;,
    &quot;test:debug&quot;: &quot;node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand&quot;,
    &quot;test:e2e&quot;: &quot;jest --config ./test/jest-e2e.json&quot;
  },</code></pre>
<p>For now, we only need <code>start:dev</code> to run the development version. In the <code>src</code> folder, you can find <code>main.ts</code>, which is the entry point to our API, along with <code>app.controller.ts</code>, <code>app.module.ts</code>, and <code>app.service.ts</code>. You can find a perfect explanation of the NestJS architecture in the chapters <a href="https://docs.nestjs.com/controllers">Controllers</a>, <a href="https://docs.nestjs.com/providers">Providers</a>, and <a href="https://docs.nestjs.com/modules">Modules</a> in the NestJS documentation.</p>
<p><code>main.ts</code> is pretty simple. Just includes <code>@netjs/core</code>, <code>app.module</code> and bootstrap our application.</p>
<pre><code class="language-typescript">import { NestFactory } from &#039;@nestjs/core&#039;;
import { AppModule } from &#039;./app.module&#039;;

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}

bootstrap();</code></pre>
<p>When you run <code>npm run start:dev</code>, the API will run on port 3000, and you will be able to access it at <code>http://localhost:3000</code>.</p>
<p>Controllers are where you define your routes. In <code>app.controller.ts</code>, there is one <code>GET</code> route.</p>
<pre><code class="language-typescript">import { Controller, Get } from &#039;@nestjs/common&#039;;
import { AppService } from &#039;./app.service&#039;;

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}</code></pre>
<p>The <code>@Get</code> decorator without parameters in <code>app.controller.ts</code> indicates that you will access this route with <code>/</code>. It's the root route, and you can access it at <code>http://localhost:3000</code>. This route calls the service method <code>getHello()</code>, which returns the string <code>Hello World!</code>. Services are where your business logic resides.</p>
<pre><code class="language-typescript">import { Injectable } from &#039;@nestjs/common&#039;;

@Injectable()
export class AppService {
  getHello(): string {
    return &#039;Hello World!&#039;;
  }
}</code></pre>
<p>You can access <code>http://localhost:3000</code> in your browser, and if the development server is running, you will see <code>Hello World!</code>. However, as an API developer, you may want a better way to call your API during development. I recommend using <a href="https://insomnia.rest/">Insomnia</a>.</p>
<p>When you call <code>http://localhost:3000</code> using Insomnia, you will get the same result as in the browser. However, as you add more routes and JSON responses, you will appreciate the usefulness of Insomnia.</p>
<pre><code>Hello World!</code></pre>
<p><code>Hello World</code> is okay, but not very useful. Let's build something more meaningful.</p>
<p>First, we should discuss how to organize our routes to avoid a mess later. A good way is to organize them into <code>resources</code>. A resource can be <code>user</code>, <code>article</code>, <code>comment</code>, etc. For resource bases, we will use plurals, for example, <code>users</code>, <code>articles</code>, and <code>comments</code>. It is a good practice to follow <a href="https://restfulapi.net/">REST</a> principles when creating an API. One of my favorite articles on this topic is <a href="https://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api">Best Practices for Designing a Pragmatic RESTful API</a>.</p>
<p>Sometimes it is easier for programmers to use just <code>GET</code> and <code>POST</code> methods for all routes, but this does not adhere to <code>RESTful</code> principles. <code>RESTful</code> principles provide strategies to handle <a href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete">CRUD</a> actions. It is better to use the full potential of <code>HTTP</code> methods. For example, when we take the resource <code>user</code>:</p>
<ul>
<li><code>GET /users</code> - retrieves a list of users</li>
<li><code>GET /users/1</code> - retrieves the user with id 1</li>
<li><code>POST /users</code> - creates a new user</li>
<li><code>PUT /users/1</code> - updates the user with id 1</li>
<li><code>PATCH /users/1</code> - partially updates the user with id 1</li>
<li><code>DELETE /users/1</code> - deletes the user with id 1</li>
</ul>
<p>You can also combine resources. For instance, to get the articles for a user, one route could be <code>GET /users/1/articles</code>.</p>
<p>If you want to like an article, the API endpoint could be <code>PUT /articles/1/like</code>. You can use aliases, filtering, sorting, limiting, and pagination constructs, but this is a complex and highly opinionated field suitable for many articles. I think the best quick dive is provided in the article I mentioned earlier, written by <a href="https://www.vinaysahni.com/">Vinay Sahni</a>.</p>
<p>Earlier in the article, I said &quot;Let's build something more meaningful,&quot; but that was a lie. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> For a quick demonstration of how to create a resource and follow methods, we will use something completely useless.</p>
<p>We will create a route <code>GET /zodiac-signs</code>. This route will return a list of zodiac signs with date ranges. I borrowed the list from <a href="https://github.com/helmasaur/zodiac-signs/blob/main/data/zodiac.json">here</a>.</p>
<p>To create a NestJS resource, we will use the <code>nest cli</code>.</p>
<pre><code class="language-shell">nest g res zodiac-signs --no-spec</code></pre>
<ul>
<li><code>nest</code> - nest command</li>
<li><code>g</code> - generate</li>
<li><code>res</code> - resource</li>
<li><code>zodiac-sign</code> - resource-name</li>
<li><code>--no-spec</code> - do not generate tests</li>
</ul>
<p>After you enter the command, you will be asked what type of transport layer you want to use. Choose REST API. The next question will be whether you would like to create CRUD entry points. I choose no; I will create them on my own.</p>
<p>When it is done, in your <code>src</code> folder, you will see a folder named <code>zodiac-signs</code>, and it will contain <code>zodiac-signs.controller.ts</code>, <code>zodiac-signs.module.ts</code>, and <code>zodiac-signs.service.ts</code>.</p>
<p>Nest CLI automatically connects your new resource/module to the app.</p>
<p>We will start with <code>zodiac-signs.service.ts</code>.</p>
<pre><code class="language-typescript">import { Injectable } from &#039;@nestjs/common&#039;;

@Injectable()
export class ZodiacSignsService {
    signs = {
        aries: {
            symbol: &#039;&#x2648;&#039;,
            dateMin: &#039;2000-03-21&#039;,
            dateMax: &#039;2000-04-20&#039;,
        },
        taurus: {
            symbol: &#039;&#x2649;&#039;,
            dateMin: &#039;2000-04-21&#039;,
            dateMax: &#039;2000-05-21&#039;,
        },
        gemini: {
            symbol: &#039;&#x264a;&#039;,
            dateMin: &#039;2000-05-22&#039;,
            dateMax: &#039;2000-06-21&#039;,
        },
        cancer: {
            symbol: &#039;&#x264b;&#039;,
            dateMin: &#039;2000-06-22&#039;,
            dateMax: &#039;2000-07-22&#039;,
        },
        leo: {
            symbol: &#039;&#x264c;&#039;,
            dateMin: &#039;2000-07-23&#039;,
            dateMax: &#039;2000-08-22&#039;,
        },
        virgo: {
            symbol: &#039;&#x264d;&#039;,
            dateMin: &#039;2000-08-23&#039;,
            dateMax: &#039;2000-09-23&#039;,
        },
        libra: {
            symbol: &#039;&#x264e;&#039;,
            dateMin: &#039;2000-09-24&#039;,
            dateMax: &#039;2000-10-23&#039;,
        },
        scorpio: {
            symbol: &#039;&#x264f;&#039;,
            dateMin: &#039;2000-10-24&#039;,
            dateMax: &#039;2000-11-22&#039;,
        },
        sagittarius: {
            symbol: &#039;&#x2650;&#039;,
            dateMin: &#039;2000-11-23&#039;,
            dateMax: &#039;2000-12-21&#039;,
        },
        capricorn: {
            symbol: &#039;&#x2651;&#039;,
            dateMin: &#039;2000-12-22&#039;,
            dateMax: &#039;2000-01-20&#039;,
        },
        aquarius: {
            symbol: &#039;&#x2652;&#039;,
            dateMin: &#039;2000-01-21&#039;,
            dateMax: &#039;2000-02-19&#039;,
        },
        pisces: {
            symbol: &#039;&#x2653;&#039;,
            dateMin: &#039;2000-02-20&#039;,
            dateMax: &#039;2000-03-20&#039;,
        },
    };

    findAll() {
        return this.signs;
    }
}</code></pre>
<p>In the <code>ZodiacSignsService</code> class, we have our logic. The list of signs is stored as a class property named <code>signs</code>. The method that returns this list is <code>findAll()</code>. It is a good practice for the route <code>GET /zodiac-signs</code> to use the service method <code>findAll</code>, and for <code>GET /zodiac-signs/:name</code> to use the service method <code>findOne</code>. This uniform naming system will help you orient yourself in a large code base.</p>
<p>Next will be <code>zodiac-signs.controller.ts</code>.</p>
<pre><code class="language-typescript">import { Controller, Get } from &#039;@nestjs/common&#039;;
import { ZodiacSignsService } from &#039;./zodiac-signs.service&#039;;

@Controller(&#039;zodiac-signs&#039;)
export class ZodiacSignsController {
  constructor(private readonly zodiacSignsService: ZodiacSignsService) {}

  @Get()
  findAll() {
    return this.zodiacSignsService.findAll();
  }
}</code></pre>
<p>We create a method <code>findAll</code> decorated with <code>@Get</code> decorator, which, without parameters, instructs the app router to point to the <code>findAll</code> method in the <code>ZodiacSignsController</code> in response to a <code>GET /zodiac-signs</code> request.</p>
<p>That's all for now. Make sure the development server is running (<code>npm run start:dev</code>). Then, you can access <code>http://localhost:3000/zodiac-signs</code>. The expected result is the same JSON as we have in <code>ZodiacSignsService</code>.</p>
<p>Okay, it's not much, but it's enough to get started. In the next chapter, we'll take a look at DTOs (Data Transfer Objects).</p>
<p>You can find project on my <a href="https://github.com/eduardtomasek/hardwired-nestjs-chapter-01-new-project">GitHub</a>.</p>
<p>Happy coding!</p>

<div class="twitter-share"><a href="https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.hardwired.dev%2F2024%2F06%2F09%2Fnestjs-chapter-01-new-project%2F&#038;via=hessevalentino" class="twitter-share-button">Tweet</a></div><p>The post <a href="https://www.hardwired.dev/2024/06/09/nestjs-chapter-01-new-project/">NestJS Chapter 01 – New Project</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>NodeJS develompent v Dockeru</title>
		<link>https://www.hardwired.dev/2022/09/17/nodejs-develompent-v-dockeru/</link>
		
		<dc:creator><![CDATA[John Doe]]></dc:creator>
		<pubDate>Sat, 17 Sep 2022 12:39:52 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Různé]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[docker-compose]]></category>
		<category><![CDATA[expressjs]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[nodejs]]></category>
		<category><![CDATA[nvm]]></category>
		<category><![CDATA[vagrant]]></category>
		<category><![CDATA[vscode]]></category>
		<guid isPermaLink="false">https://hessevalentino.cz/?p=378</guid>

					<description><![CDATA[<p>Pokud se motáte okolo webového vývoje (frontendy, api a pod...) a používáte JavaScript (respektive NodeJS), tak jste se určitě už &#62;&#62;&#62;</p>
<p>The post <a href="https://www.hardwired.dev/2022/09/17/nodejs-develompent-v-dockeru/">NodeJS develompent v Dockeru</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>Pokud se motáte okolo webového vývoje (frontendy, api a pod...) a používáte <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript">JavaScript</a> (respektive <a href="https://nodejs.org/en/">NodeJS</a>), tak jste se určitě už setkali s následujícím problémem. Různé projekty jsou napsány pod různými verzemi programovacího jazyka a ne vždy je možné vše upgradovat na poslední verzi. </p>
<p><span id="more-378"></span></p>
<ul>
<li>Můžete používat knihovny, které ještě nejsou upraveny pro novou verzi.</li>
<li>Starší verze frameworku s poslední verzí jazyka nefunguje.</li>
<li>Zpětná nekompatibilita.</li>
<li>Prostě nejsou peníze nebo není čas zabývat se přechodem a přepisem aplikace na poslední verzi.</li>
</ul>
<p>Důvodů může být milión, ale klíčové je to, že pokud jste to vy co musí do těchto  projektů zasahovat, tak musíte provozovat více verzí jazyka.</p>
<p>Pokud se potýkáte s tímto problémem, tak nehledě na jakém operačním systému se nacházíte, budou scénáře podobné.</p>
<h2>Scénář 1 - Jedna verze v systému</h2>
<p>Tohle je pro popisovaný problém asi nejhorší situace. Máte v systému jednu verzi jazyka. Všechny projekty, na kterých pracujete, musejí běžet pod touhle verzí. Zpravidla to skončí tak, že verze jazyka bude taková, jakou potřebuje ten nejstarší (legacy) projekt. Může vás to zablokovat na tolik, že nebudete moci použít poslední verze frameworků nebo poslední funkcionalitu, protože nebudou tak starou verzi jazyka podporovat.</p>
<h2>Scénář 2 - NVM</h2>
<p><a href="https://github.com/nvm-sh/nvm">Node Version Manager</a> (NVM) je utilita, která vám umožní provozovat více verzí jazyka na jednom stroji a přepínat mezi nimi. Existuje jak pro Linux, MacOs, tak i pro Windows. Ve chvíli kdy se přepínáte mezi verzemi a používáte současně jednu, je to přímočaré a elegantní řešení. Ve chvíli, kdy potřebujete mít několik projektů puštěných naráz, pod různými verzemi jazyka, už samozřejmě vyžaduje určitou míru konfigurace. Ale zrovna k tomuto scénáři nemám moc co říct, protože jsem provozoval jen tu nejprimitivnější formu čistě přepínání mezi verzemi. Každopádně se jedná o funkční řešení.</p>
<h2>Scénář 3 - Vagrant</h2>
<p><a href="https://www.vagrantup.com/">Vagrant od HashiCorp</a> používá pro oddělení prostředí virtualizaci. Vytvoříte předpis, který nakonfiguruje virtuální stroj, ve kterém následně aplikaci vyvíjíte. Je možné nakonfigurovat celý ekosystém, aplikace, databáze, cache atd.  Teoreticky je to geniální věc. Nehledě na systém máte předpis, který spustíte na jakémkoliv systému a vytvoří vám stejné prostředí pro vývoj. V praxi to už tak veselé nebylo. Je pravda, že jsem Vagrant použil naposledy před několika lety. Problémy byly zpravidla nějaká specifika operačních systému, zvláště Windows. Nebo situace co se musely řešit &quot;hackem&quot;, protože ještě neexistovalo nativní řešení a samozřejmě hromada virtuálních mašin, když bylo prostředí pro vývoj rozsáhle. I tak jsem na tom byl nějakou dobu schopný vyvíjet a šlo to docela dobře. Čas pokročil a určitě byla hromada věcí dotažena. Určitě se jedná o funkční řešení.</p>
<h2>Scénář 4 - Docker</h2>
<p>Jak už název článku napovídá, budeme řešit <a href="https://www.docker.com/">Docker</a>. Docker používá kontejnery. Kontejner je softwarová jednotka, která zapouzdřuje kód i s jeho závislostmi. Na rozdíl od standardní virtualizace, nerozebíhá znovu celý operační systém, ale používá operační systém hostitele. Nejlíp to asi vysvětlí přímo citace ze stránek Dockeru.</p>
<blockquote>
<p>A container is a standard unit of software that packages up code and  all its dependencies so the application runs quickly and reliably from  one computing environment to another. A Docker container image is a  lightweight, standalone, executable package of software that includes  everything needed to run an application: code, runtime, system tools,  system libraries and settings.</p>
<p>Container images become containers at runtime and in the case of Docker containers – images become containers when they run on <a href="https://www.docker.com/products/container-runtime">Docker Engine</a>. Available for both Linux and Windows-based applications, containerized  software will always run the same, regardless of the infrastructure.  Containers isolate software from its environment and ensure that it  works uniformly despite differences for instance between development and staging.</p>
<p>from <a href="https://www.docker.com/resources/what-container/">https://www.docker.com/resources/what-container/</a></p>
</blockquote>
<p>V praxi to znamená, že máte v kontejneru souborový systém operačního systému dle libosti. Doinstalujete si potřebné balíčky pro běh vašeho projektu a tento kontejner můžete izolovaně pouštět tam, kde jsou kontejnery podporované. Speciálně Docker funguje pod Linuxem, MacOs i Windows.</p>
<pre><code>+------------++-----------+
|    APP1    ||   APP2    |
+------------++-----------+
+------------++-----------+
|  Bin/Libs  ||  Bin/Libs |
+------------++-----------+
+-------------------------+
|         Docker          |
+-------------------------+
+-------------------------+
|    Operační systém      |
+-------------------------+
+-------------------------+
|         Server          |
+-------------------------+</code></pre>
<p>&quot;Back in my days&quot;, když jsem si chtěl na serveru rozjet nějaké služby, buď jsem provozoval nějakou virtualizaci nebo jsem to všechno naplácal do jednoho operačního systému. Jedno ze zásadních úskalí bylo to, že různé služby potřebovaly různé balíky, verze knihoven a míru konfigurace. Pokud člověk nebyl dostatečně obezřetný mohl si &quot;roze***t&quot; celý systém a vše poslat do kytek. V lepším případě byla mašina v jakémsi meta ezo stavu, kdy něco jelo a něco ne.</p>
<p>S Dockerem hromada problémů opadla. Každá služba je izolovaný kontejner, který si své závislosti bere sebou. Pokud něco nefunguje, vadný kontejner se vymaže, ale vše ostatní jede dál. Drtivé množství běžných služeb (wiki, databáze, ...) mají už dnes nachystané a nakonfigurované obrazy. V uvozovkách je stačí jen spustit. Jako všechno si to sebou nese i negativa. Neaktualizované knihovny v kontejneru jsou bezpečnostní riziko. Nebo pokud si nevytváříte kontejner sami tak musíte důvěřovat autorovi, že tam nenasadil nějakou breberku. Ale vždy je něco za něco.</p>
<p>Jak už asi tušíte, z tohoto stručného popisu, použití pro výše popsaný problém bude jasné. Vytvoří se pro projekt Docker kontejner a tak budou všechny závislosti projektu izolovány od hlavního operačního systému. Takhle můžete mít pohodlně puštěné aplikace pod různou verzí NodeJS na jednom stroji. Je to v podstatě jako Vagrant, <a href="https://www.virtualbox.org/">VirtualBox</a> nebo obecně virtualizace. Akorát teda ne tak úplně. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>Nešpinit systém, na kterém vyvíjíte, závislostmi projektu je podle mě dlouhodobě udržitelná cesta.</p>
<p>Plus mají kontejnery dnes ještě jednu výhodu. <a href="https://aws.amazon.com/getting-started/hands-on/deploy-docker-containers/">Cloudové služby</a> vám zpravidla umožňují posílat kontejnery i do produkce.</p>
<h2>Čestná zmínka</h2>
<p>Výše uvedené scénáře nejsou určitě jediné, ale jsou to ty, se kterými jsem se setkal osobně.</p>
<p>Minimálně ještě existuje možnost vyvíjet na vzdáleném operačním systému přes <a href="https://cs.wikipedia.org/wiki/Secure_Shell">SSH</a>. <a href="https://code.visualstudio.com/">Visual Studio Code</a> tento <a href="https://code.visualstudio.com/docs/remote/ssh">vzdálený vývoj</a> umožňuje. Jako taky možnost, ale za mě teda trochu exotická. Ale když není zbytí, lepší než drátem do oka.</p>
<h2>NodeJS projekt v Dockeru</h2>
<blockquote>
<p>Toto není kompletní návod pro člověka, který se v životě neotřel o Docker nebo o NodeJS a vývoj API. Do takových podrobností článek nejde. Zabývá se jak rozjet projekt v Dockeru a předpokládá už určité znalosti. Pardon. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
</blockquote>
<p>V první řadě budeme potřebovat <a href="http://wordpress.hardwired.dev/instalace-dockeru/">nainstalovat Docker</a>. Případně na desktopu (a hlavně na Windows) to bude <a href="https://docs.docker.com/desktop/">Docker Desktop</a>.</p>
<p>Pokusíme se rozjet vývoj <a href="https://zdrojak.cz/clanky/rest-architektura-pro-webove-api/">REST API</a> s použitím <a href="https://expressjs.com/">ExpressJs</a>.</p>
<p>Pro náš projekt budeme mít následující strukturu.</p>
<pre><code class="language-bash">nodejs-docker-workflow \
    .dockerignore
    .env
    Dockerfile
    index.js
    package.json
    package-lock.json</code></pre>
<p><code>pakcage.json</code> obsahuje konfiguraci projektu.</p>
<pre><code class="language-json">{
  &quot;name&quot;: &quot;nodejs-docker-workflow&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;main&quot;: &quot;index.js&quot;,
  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;node index.js&quot;,
    &quot;dev&quot;: &quot;nodemon -L index.js&quot;
  },
  &quot;keywords&quot;: [],
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;,
  &quot;dependencies&quot;: {
    &quot;express&quot;: &quot;^4.18.1&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;nodemon&quot;: &quot;^2.0.20&quot;
  }
}</code></pre>
<p>V části závislostí budeme pro náš jednoduchý projekt potřebovat pouze balíček <a href="https://www.npmjs.com/package/express">express</a>. V rámci vývojových závislostí (devDependencies) budeme používat <a href="https://www.npmjs.com/package/nodemon">nodemon</a>. Ten nám umožní restart serveru, pokud se vyskytne změna v hlídaném adresáři.</p>
<p><code>index.js</code> obsahuje kód našeho REST API.</p>
<pre><code class="language-javascript">const express = require(&#039;express&#039;)

const app = express()

app.get(&#039;/&#039;, (req, res) =&gt; {
    res.send({
        data: {
            message: &#039;Hello world!&#039;,
            exclamation: &#039;!!!&#039;,
        },
    })
})

const port = process.env.PORT || 3000

app.listen(port, () =&gt; console.log(`listening on port ${port}`))</code></pre>
<p>Primitivní API vracející &quot;Hello world!&quot;.</p>
<p><code>Dockerfile</code> obsahuje sestavení našeho obrazu kontejneru.</p>
<pre><code class="language-dockerfile">FROM node:16
WORKDIR /app
COPY package*.json .
RUN npm install
COPY . ./
ENV PORT 3000
EXPOSE $PORT
CMD [&quot;npm&quot;, &quot;run&quot;, &quot;dev&quot;]</code></pre>
<p><code>FROM node:16</code> říká, že použijeme základní image, na kterém je už nachystán NodeJS verze 16.</p>
<p><code>WORKDIR /app</code> nás v rámci kontextu přesune do složky <code>/app</code>.</p>
<p><code>COPY package*.json</code> . překopíruje do obrazu do <code>/app</code> soubor <code>package.json</code>.</p>
<p><code>RUN npm install</code> spustí instalaci závislostí na základe <code>package.json</code>.</p>
<p><code>COPY . ./</code> překopíruje soubory z aktuálního adresáře do obrazu do <code>/app</code>.</p>
<p><code>ENV PORT 3000</code> vytvoří proměnou prostředí.</p>
<p><code>CMD [&quot;npm&quot;, &quot;run&quot;, &quot;dev&quot;]</code> spustí skript definovaný v <code>package.json</code>, který spustí nodemon.</p>
<p><code>.dockerignore</code> obsahuje seznam souboru a složek co se nebudou kopírovat do obrazu.</p>
<pre><code class="language-bash">node_modules
Dockerfile
.dockerignore
.git
.gitignore
README.md
docker-compose*</code></pre>
<p><code>.env</code> je seznam proměnných prostředí, které chceme aplikovat na kontejner.</p>
<pre><code>PORT=4000</code></pre>
<p>Základní projekt máme nachystaný. A sestavíme na základě <code>Dockerfile</code> obraz pro náš kontejner.</p>
<pre><code class="language-bash">docker build -t node-app-image .</code></pre>
<p>Následně pak můžeme překontrolovat, že obraz skutečně existuje.</p>
<pre><code class="language-bash">docker image ls</code></pre>
<p>Obraz je nachystaný a můžeme spustit samotný kontejner.</p>
<pre><code class="language-bash"># WINDOWS %cd%
# POWERSHELL ${pwd}
# MAC, LINUX $(pwd)

# --env PORT=4000
# --env-file ./.env

docker run -p 3000:4000 -d --name node-app --env-file ./.env -v %cd%:/app -v /app/node_modules node-app-image</code></pre>
<p><code>-p 3000:4000</code> přesměruje port 3000 z hostitelského systému na port 4000 Docker kontejneru.</p>
<p><code>-d</code> spustí Docker kontejner na pozadí.</p>
<p><code>--name node-app</code> pojmenuje kontejner.</p>
<p><code>--env-file ./.env</code> nastaví proměnné systému na základě souboru <code>.env</code>.</p>
<p><code>-v %cd%:/app</code> zajistí zrcadlení aktuálního adresáře a jeho změny do <code>/app</code> v kontejneru.</p>
<p><code>-v /app/node_modules</code> vytvoří volume pro node moduly. Díky tomu se nestane to, že přes zrcadlený adresář pošleme příkaz k jejich smazání v kontejneru. Je to trochu &quot;ohák&quot;, ale funční.</p>
<p><code>node-app-image</code> je název obrazu na základě kterého vytváříme kontejner.</p>
<p>Pokud nedostaneme nějaké chybové hlášení, můžeme zkontrolovat, že vše jede.</p>
<p>Můžeme se podívat na aktuálně běžící kontejnery.</p>
<pre><code class="language-bash">docker ps</code></pre>
<p>A můžeme také zkontrolovat logy pro konkrétní kontejner.</p>
<pre><code class="language-bash">docker logs node-app</code></pre>
<p>Když do prohlížeče zadáme <code>localhost:3000</code> dostaneme následující.</p>
<pre><code class="language-json">{&quot;data&quot;:{&quot;message&quot;:&quot;Hello world!&quot;,&quot;exclamation&quot;:&quot;!!!&quot;}}</code></pre>
<p>Pokud v souboru <code>index.js</code> upravíme odpověď serveru, <code>nodemon</code> na to zareaguje a restartuje API s aktuální změnou.</p>
<p>Jestliže se potřebujeme &quot;přihlásit&quot; dovnitř kontejneru do příkazové řádky, použijeme <code>docker exec</code>.</p>
<pre><code class="language-bash">docker exec -it node-app bash</code></pre>
<p>V této chvíli máme plně funkční NodeJS projekt v Dockeru. Pokud přidáme nebo odebereme balíčky, musím znovu sestavit obraz pomocí <code>docker build -t node-app-image .</code> a Docker kontejner spustit.</p>
<p>Předtím je teda nutné kontejner zabít, to uděláme pomocí <code>docker rm</code>.</p>
<pre><code class="language-bash">docker rm node-app -fv</code></pre>
<p><code>-fv</code> odstraní i běžící kontejner (nemusíme zastavovat) a na něj navázané anonymní volumes (svazky).</p>
<p>Tohle je taková &quot;základní&quot; verze. Spouštění Docker kontejneru, s veškerou konfigurací v příkazové řádce může být po čase otrava. Jednodušším řešením je použití <a href="https://docs.docker.com/compose/gettingstarted/">Docker-Compose</a>.</p>
<p>V našem projektu vytvoříme soubor <code>docker-compose.yml</code>.</p>
<pre><code class="language-yaml">version: &quot;3&quot;
services:
  node-app:
    container_name: node-app
    build: .
    ports:
      - &quot;3000:4000&quot;
    volumes:
      - ./:/app
      - /app/node_modules
    env_file:
      - ./.env
#    environment:
#      - PORT=4000 </code></pre>
<p><code>version: &quot;3&quot;</code> je <a href="https://docs.docker.com/compose/compose-file/compose-versioning/">verze zápisu Docker Compose</a> souboru.</p>
<p><code>node-app:</code> uvozuje sekci našeho kontejneru.</p>
<p><code>container_name: node-app</code> pojmenuje náš kontejner. Pokud ho nepojmenujeme sami, Docker to udělá za nás.</p>
<p><code>build: .</code> sestaví obraz pomocí <code>Dockerfile</code>.</p>
<p><code>ports:</code> přesměrování portů.</p>
<p><code>volumes:</code> seznam volumes.</p>
<p><code>env_file:</code> nastavuje proměnné prostředí.</p>
<p>Docker Compose soubor jen kopíruje to, co jsme nastavovali pro <code>docker run</code>. Ale takhle nám zůstane nastavení pěkně a strukturovaně uloženo.</p>
<p>Předpis spustíme pomocí příkazu <code>docker-compose</code>.</p>
<pre><code class="language-bash">docker-compose up -d</code></pre>
<p>Pokud přidáme parametr <code>--build</code>, tak se při každém spuštění znovu sestaví obraz.</p>
<pre><code class="language-bash">docker-compose up -d --build</code></pre>
<p>Pomocí <code>docker-compose</code> provádíme i smazání.</p>
<pre><code class="language-bash">docker-compose down -v</code></pre>
<p><code>-v</code> jako v předchozím případě smaže i připojené anonymní volumes.</p>
<p>Tohle je už o něco lepší verze, ale nepočítá s tím, že bychom chtěli různá prostředí. Například <code>development</code> a <code>production</code>. Budeme muset upravit <code>Dockerfile</code>, <code>docker-compose.yml</code> a přidat <code>docker-compose.dev.yml</code> a <code>docker-compose.prod.yml</code>.</p>
<p>Do <code>Dockerfile</code> přidáme podmínku pro různá prostředí.</p>
<pre><code class="language-dockerfile">FROM node:16
WORKDIR /app
COPY package*.json .

ARG NODE_ENV
RUN if [ &quot;$NODE_ENV&quot; = &quot;development&quot; ]; \
        then npm install; \
        else npm install --only=production; \
        fi

COPY . ./
ENV PORT 3000
EXPOSE $PORT
CMD [&quot;node&quot;, &quot;index.js&quot;]</code></pre>
<p><code>ARG NODE_ENV</code> definujeme použití argumentu <code>NODE_ENV</code>.</p>
<p><code>RUN if [ &quot;$NODE_ENV&quot; = &quot;development&quot; ]; \</code> na základě aktuální typu prostředí provedeme klasický <code>npm install</code> nebo produkční.</p>
<p><code>CMD [&quot;node&quot;, &quot;index.js&quot;]</code> je příkaz do produkčního prostředí, protože nespouštíme <code>nodemon</code>. Každopádně ho stejně budeme definovat znovu v Docker Compose souborech.</p>
<p><code>docker-compose.yml</code> trošku zeštíhlíme a necháme v něm jen společná nastavení pro všechna prostředí.</p>
<pre><code class="language-yaml">version: &quot;3&quot;
services:
  node-app:
    container_name: node-app
    build: .
    ports:
      - &quot;3000:4000&quot;
    environment:
      - PORT=4000  </code></pre>
<p><code>docker-compose.dev.yml</code> nastavím pro naše <code>development</code> prostředí.</p>
<pre><code class="language-yaml">version: &quot;3&quot;
services:
  node-app:
    build:
      context: . 
      args:
        NODE_ENV: development
    volumes:
      - ./:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development  
    command: npm run dev</code></pre>
<p>Všimněte si, že jsme rozšířili definici <code>build</code> a přidali argument <code>NODE_ENV</code>, který se používá v <code>Dockerfile</code>. Nastavení <code>volumes</code> je stejné jako předtím a přepsali jsme <code>CMD</code> v <code>Dockerfile</code> na náš <code>development</code> příkaz.</p>
<p><code>docker-compose.prod.yml</code> bude jednodušší, protože pro produkci nepotřebujeme zrcadlit adresáře.</p>
<pre><code class="language-yaml">version: &quot;3&quot;
services:
  node-app:
    build:
      context: . 
      args:
        NODE_ENV: production
    environment:
      - NODE_ENV=production
    command: node index.js</code></pre>
<p>Principiálně je to to samé co <code>docker-compose.dev.yml</code>.</p>
<p>Pokud budeme chtít spustit <code>development</code> verzi, zavoláme.</p>
<pre><code class="language-bash">docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d</code></pre>
<p>Popřípadě, pokud chceme spustit i vytváření obrazu.</p>
<pre><code class="language-bash">docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build</code></pre>
<p>Odstranění kontejneru provedeme promocí.</p>
<pre><code class="language-shell">docker-compose -f docker-compose.yml -f docker-compose.dev.yml down -v</code></pre>
<p>Pro produkční build to bude analogické.</p>
<pre><code class="language-bash">docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
docker-compose -f docker-compose.yml -f docker-compose.prod.yml down -v</code></pre>
<p>TADÁ a to je vše přátele. Aplikace funguje pořád stejně, ale už můžeme rozlišovat mezi <code>development</code> a <code>production</code> prostředtím.</p>
<hr />
<p><em>ad1)</em> Článek popisuje pouze absolutní základ, pravá síla Dockeru se projeví ve chvíli, kdy si nakonfigurujete kompletní ekosystém a budete ho schopni jednoduše replikovat.</p>
<p>ad2) Článek ukazuje situaci, kdy nebudete mít na svém stroji nainstalován NodeJS a nepustíte <code>npm install</code> na svém stroji. Tím si nevygenerujete <code>package-lock.json</code>. To může být problém při generování produkčních kontejnerů. <code>package-lock.json</code> obsahuje deterministický popis závislostí. Do produkce chcete jít s takovým stromem závislostí, který už máte odzkoušený. Pro doplnění citace z <a href="https://docs.npmjs.com/cli/v8/configuring-npm/package-lock-json">docs.npm.com</a>.</p>
<blockquote>
<p><code>package-lock.json</code> is automatically generated for any operations where npm modifies either the <code>node_modules</code> tree, or <code>package.json</code>. It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.</p>
<p>Describe a single representation of a dependency tree such that teammates, deployments, and continuous integration are guaranteed to install exactly the same dependencies.</p>
<p>from <a href="https://docs.npmjs.com/cli/v8/configuring-npm/package-lock-json">https://docs.npmjs.com/cli/v8/configuring-npm/package-lock-json</a></p>
</blockquote>
<p>Proto je vhodnější postup na hostitelské systému používat <code>npm i</code> pro instalaci nových balíčku do projektu. Tím se bude generovat i <code>package-lock.json</code>. Toto nijak neomezuje používání rozličných verzí NodeJS v kontejnerech.</p>
<p>ad3) Docker se chová tak, že spustí příkaz a když doběhne, tak se vypne. V případě, že rozjíždíte NodeJs API, tak je to jedno. Tam se předpokládá, že pouštíte nějaký <code>nodemon</code> nebo něco co udrží API v běhu. Pokud ale chcete vyvíjet něco co neběží ve smyčce a z <code>Dockerfile</code> odeberete <code>CMD příkaz</code>, tak se <code>Docker container</code> spustí a úspěšně ukončí. Jde tím předejít přidáním parametru <code>tty</code>.<br />
Ten zajistí, že se kontejner hned neukončí.</p>
<p>Pro <code>docker-compose</code>:</p>
<pre><code class="language-yaml">mydocker:
    tty: true</code></pre>
<p>Pro <code>docker run</code>:</p>
<pre><code class="language-bash">docker run -d --tty ......</code></pre>

<div class="twitter-share"><a href="https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.hardwired.dev%2F2022%2F09%2F17%2Fnodejs-develompent-v-dockeru%2F&#038;via=hessevalentino" class="twitter-share-button">Tweet</a></div><p>The post <a href="https://www.hardwired.dev/2022/09/17/nodejs-develompent-v-dockeru/">NodeJS develompent v Dockeru</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
