<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Глеб</title><generator>teletype.in</generator><description><![CDATA[Пишу про фронтенд разработку:)]]></description><image><url>https://img2.teletype.in/files/94/41/9441a466-7e66-49fa-a78e-f1f4e6ce7a31.png</url><title>Глеб</title><link>https://teletype.in/@dev.pologov</link></image><link>https://teletype.in/@dev.pologov?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=dev.pologov</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/dev.pologov?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/dev.pologov?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Fri, 15 May 2026 16:14:36 GMT</pubDate><lastBuildDate>Fri, 15 May 2026 16:14:36 GMT</lastBuildDate><item><guid isPermaLink="true">https://teletype.in/@dev.pologov/1pRYznfsjar</guid><link>https://teletype.in/@dev.pologov/1pRYznfsjar?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=dev.pologov</link><comments>https://teletype.in/@dev.pologov/1pRYznfsjar?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=dev.pologov#comments</comments><dc:creator>dev.pologov</dc:creator><title>Grind 75. Valid Parentheses (2/75) </title><pubDate>Fri, 19 Jan 2024 08:52:12 GMT</pubDate><media:content medium="image" url="https://img3.teletype.in/files/67/15/67159d5d-9680-4a6a-91c8-bb745a7b69b6.png"></media:content><category>Grind75</category><description><![CDATA[<img src="https://img3.teletype.in/files/ab/64/ab6482f6-5600-4784-b5cf-dce5a544ccb9.png"></img>Статья-решение второй задачи из списка для подготовки к IT собеседованиям Grind 75.]]></description><content:encoded><![CDATA[
  <figure id="0a7m" class="m_original">
    <img src="https://img3.teletype.in/files/ab/64/ab6482f6-5600-4784-b5cf-dce5a544ccb9.png" width="1000" />
  </figure>
  <p id="TOx8">Статья-решение <a href="https://leetcode.com/problems/valid-parentheses/submissions/1146887558/" target="_blank">второй задачи</a> из списка для подготовки к IT собеседованиям Grind 75.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="ZpNh"><strong>Описание задачи:</strong></h2>
  </section>
  <p id="UyYM">На вход подается строка <code>s</code> состоящая из символов <code>&#x27;(&#x27;</code>, <code>&#x27;)&#x27;</code>, <code>&#x27;{&#x27;</code>, <code>&#x27;}&#x27;</code>, <code>&#x27;[&#x27;</code> или <code>&#x27;]&#x27;</code></p>
  <p id="RCGa">Необходимо проверить, является ли строка валидной.</p>
  <p id="eYaM">Строка является валидной, если соответствует следующим пунктам:</p>
  <p id="FMS3">1) Открытые скобки должны быть закрыты скобками того же типа.<br />2) Открытые скобки должны быть закрыты в правильном порядке.<br />3) Каждая закрытая скобка имеет соответствующую открытую скобку того же типа.</p>
  <p id="3kJr">Примеры:</p>
  <pre id="OgX8">Пример 1:
Input: s = &quot;()&quot;
Output: true</pre>
  <pre id="omUX">Пример 2:
Input: s = &quot;()[]{}&quot;
Output: true</pre>
  <pre id="xk3B">Пример 3:
Input: s = &quot;(]&quot;
Output: false</pre>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="0Ve7">Решение</h2>
  </section>
  <p id="Zk5J">Для решение данной задачи мы будем использовать структуру данных Stack, про нее можете прочитать <a href="https://teletype.in/@dev.pologov/JBY1OIA4MQb" target="_blank">тут.</a></p>
  <p id="ol4s">Алгоритм для решения задачи будет следующим:</p>
  <p id="Pcql">Сначала мы проверим, что длина строки больше одного символа. Затем мы объявим стек в виде массива и хеш-таблицу в виде закрытых скобок как ключей и открытых скобок как значений. Смысл в том, что мы будем проверять каждый символ строки. Если он будет равняться открытой скобке, то мы будем добавлять его в наш стек. Если нет, то мы будем проверять, является ли последний элемент нашего стека противоположным элементом закрытой скобке по типу. Если да, то мы удалим последний элемент с помощью правила &quot;Последним пришел - Первым вышел&quot;. Все это позволит нам проверить, правильно ли сбалансирована строка. Если в конце стек будет пустым, значит все элементы были в правильном порядке.</p>
  <figure id="tHp2" class="m_original">
    <img src="https://img3.teletype.in/files/a0/9f/a09fedb0-3478-4a73-85cc-01aec0ef9d7f.png" width="1000" />
  </figure>
  <p id="51d4">Теперь приступим к реализации нашего алгоритма:</p>
  <p id="1NWZ">1) Создадим функцию <code>isValid</code> с одним параметром <code>s</code>, которая будет проверять переданную строку.</p>
  <pre id="WP5a" data-lang="javascript">const isValid = (s) =&gt; {
 // code
}</pre>
  <p id="zFtK">2) После объявления функции в условии <code>if</code> проверим длину строки <code>s</code>. Если длина меньше или равна 1, то возвращаем <code>false</code>, так как строка с одной или менее символов не может быть сбалансированной, потому что у каждой открывающей скобки должна быть закрывающая.</p>
  <pre id="teJT" data-lang="javascript">if (s.length &lt;= 1) return false</pre>
  <p id="sw9v">3) Объявим массив, который будет играть роль стека.</p>
  <pre id="yINd" data-lang="javascript">const stack = []</pre>
  <p id="nSpQ">4) Объявим хэш-таблицу с ключами в виде закрытых скобок и значениями в виде открытых. </p>
  <pre id="EdhM" data-lang="javascript">const braces = {
  &#x27;)&#x27;: &#x27;(&#x27;,
  &#x27;]&#x27;: &#x27;[&#x27;,
  &#x27;}&#x27;: &#x27;{&#x27;
}</pre>
  <p id="G1Yg">5) Запустим цикл for of, в котором переберем все символы <code>char</code> в переданной строке <code>s</code>.</p>
  <pre id="7tZB" data-lang="javascript">for (let char of s) {
 // code
}</pre>
  <p id="buZ5">6) Внутри цикла проверим, является ли <code>char</code> открывающей скобкой. Если да, то она добавляется в стек.</p>
  <pre id="4Flu" data-lang="javascript">for (let char of s) {
  if (!braces[char]) {
    stack.push(char) 
  } else {
    // code
  }
}</pre>
  <p id="jOpe">7) Если <code>char</code> не является открывающей скобкой, то выполняется код в блоке <code>else</code>.</p>
  <p id="YXPv">8) В блоке <code>else</code> проверим, соответствует ли последний элемент стека открывающей скобке для текущей закрывающей скобки <code>char</code>. Если да, то последний элемент удаляется из стека с помощью метода <code>pop()</code>.</p>
  <pre id="MzwO" data-lang="javascript">for (let char of s) {
  if (!braces[char]) {
    stack.push(char) 
  } else {
    if (stack[stack.length - 1] === braces[char]) {
      stack.pop()
    } else {
      // code
    }
  }
}</pre>
  <p id="NvCw">9) Если последний элемент стека не соответствует открывающей скобке для текущей закрывающей скобки, то возвращается <code>false</code>, так как скобки не сбалансированы.</p>
  <pre id="ddGv" data-lang="javascript">for (let char of s) {
  if (!braces[char]) {
    stack.push(char) 
  } else {
    if (stack[stack.length - 1] === braces[char]) {
      stack.pop()
    } else {
      return false
    }
  }
}</pre>
  <p id="4M8P">10) По окончании цикла проверяем длину стека. Если она равна 0, то все скобки сбалансированы и возвращаем <code>true</code>. Если же длина стека не равна 0, то скобки не сбалансированы и возвращаем <code>false</code>.</p>
  <p id="dHIS">Полный код функции:</p>
  <pre id="P8Uq" data-lang="javascript">const isValid = (s) =&gt; {
  if (s.length &lt;= 1) return false
   
  const stack = []
  const braces = {
    &#x27;)&#x27;: &#x27;(&#x27;,
    &#x27;]&#x27;: &#x27;[&#x27;,
    &#x27;}&#x27;: &#x27;{&#x27;
  }
   
  for (let char of s) {
    if (!braces[char]) {
      stack.push(char) 
    } else {
      if (stack[stack.length - 1] === braces[char]) {
        stack.pop()
      } else {
        return false
      }
    }
  }
  
  return stack.length === 0
}</pre>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="nUhe">Заключение</h2>
  </section>
  <p id="CVCC">Запустим код в тренажере и убедимся что мы прошли через все тесты.</p>
  <p id="wAJW">Решение так же является оптимальным, что доказывает скорость выполнения.</p>
  <figure id="Sxtg" class="m_column">
    <img src="https://img3.teletype.in/files/6a/a3/6aa38e37-7d4d-4434-bf8b-058fd66d9459.png" width="1406" />
  </figure>
  <p id="2a3O"></p>
  <p id="RABW">Подписывайтесь на мой <a href="https://t.me/days_on_front" target="_blank">канал</a>, в нем будут новые разборы и интересные статьи:)</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@dev.pologov/JBY1OIA4MQb</guid><link>https://teletype.in/@dev.pologov/JBY1OIA4MQb?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=dev.pologov</link><comments>https://teletype.in/@dev.pologov/JBY1OIA4MQb?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=dev.pologov#comments</comments><dc:creator>dev.pologov</dc:creator><title>Структура данных Stack.</title><pubDate>Tue, 16 Jan 2024 13:01:45 GMT</pubDate><media:content medium="image" url="https://img2.teletype.in/files/d5/cd/d5cd29fa-f8fb-4e41-9f6e-c81e74723aa4.png"></media:content><category>Structured Data</category><description><![CDATA[<img src="https://img2.teletype.in/files/16/d0/16d0d632-de62-4e8f-92b0-78148bf7e3d9.png"></img>В этой статье мы рассмотрим структуру данных Stack, методы работы с ним, скорость выполнения и примеры использования.]]></description><content:encoded><![CDATA[
  <p id="4OD2">В этой статье мы рассмотрим структуру данных Stack, методы работы с ним, скорость выполнения и примеры использования.</p>
  <figure id="80s2" class="m_original">
    <img src="https://img2.teletype.in/files/16/d0/16d0d632-de62-4e8f-92b0-78148bf7e3d9.png" width="1000" />
  </figure>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="sf4a">Описание</h2>
  </section>
  <p id="okk7">Простая структура данных, которая представляет собой упорядоченную коллекцию элементов, в которую добавляют элементы и затем убирают их в обратном порядке с одного конца, который обычно называется вершиной стека, т.е первый добавленный элемент удаляют последним, а последний добавленный - первым, правило звучит так &quot;Последним пришел - Первым вышел&quot; или LIFO от англ. &quot;last in, first out&quot;.</p>
  <figure id="A9bG" class="m_custom">
    <img src="https://img3.teletype.in/files/ad/5b/ad5b0ff5-968b-4e64-aab0-516ea2863bf0.png" width="873" />
    <figcaption>Stack</figcaption>
  </figure>
  <ol id="VMDq">
    <li id="7M15">Push: добавление элемента на вершину стека.</li>
    <li id="mjpV">Peek: получение значения верхнего элемента без его удаления.</li>
    <li id="h3NY">Pop: удаление элемента с вершины стека.</li>
    <li id="BjoH">isEmpty: проверка, пуст ли стек. Возвращает true, если стек пуст и false в противоположном случае.</li>
  </ol>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="rGNM">Реализация структуры Stack</h2>
  </section>
  <p id="bekk">Операция добавления и удаления элементов в стеке и очереди занимает <code>О(1)</code>, в то время как операции поиска и получение произвольного элемента имеют сложность <code>O(n)</code>. Структура Stack может быть реализована с использованием различных абстрактных типов данных, например, массивов или связанных списков. Важно выбрать оптимальную реализацию в зависимости от задачи, так как эффективность работы со стеками может сильно различаться в зависимости от используемых методов.</p>
  <p id="Y8Df">В случае с массивами, стек реализуется очень просто, элементы добавляются и удаляются конца массива.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="C7oe">Применение в программировании</h2>
  </section>
  <p id="0DoI">Структура Stack находит широкое применение в программировании:</p>
  <p id="KvxO">- Управление вызовами функций в компьютерных программах (хранение локальных переменных и адреса возврата).</p>
  <p id="vPgI">- Отмена и возврат действий в графических приложениях.</p>
  <p id="QZWR">- Реализация алгоритмов обхода графов.</p>
  <p id="cJN7">- Хранение временных данных в алгоритмах поиска и сортировки.</p>
  <p id="QwJ4">- Другие.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="F1nW">Заключение</h2>
  </section>
  <p id="y5ny">Таким образом, структура данных Stack является полезной вспомогательной структурой данных для решения каких-либо задач.</p>
  <p id="xuPW">Например, она используются как важная часть механизма управления вызовами функций во время выполнения программы. Когда программа вызывает функцию, информация о вызове (аргументы функции, адрес возврата и локальные переменные) сохраняется в стеке. Когда функция завершает свою работу, соответствующая запись извлекается из стека, возвращая управление к месту, откуда была произведена вызов функции.</p>
  <p id="ZYRE"></p>
  <p id="SGRj">Спасибо за прочтение статьи, <a href="https://t.me/days_on_front" target="_blank">подписывайтесь на канал</a>, в нем будут выходить новые интересные статьи и разборы задач с использованием структуры Stack.</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@dev.pologov/FYydAJqme1W</guid><link>https://teletype.in/@dev.pologov/FYydAJqme1W?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=dev.pologov</link><comments>https://teletype.in/@dev.pologov/FYydAJqme1W?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=dev.pologov#comments</comments><dc:creator>dev.pologov</dc:creator><title>Grind 75. Two Sum (1/75)</title><pubDate>Sun, 14 Jan 2024 17:10:48 GMT</pubDate><media:content medium="image" url="https://img1.teletype.in/files/00/97/00970062-3181-45e2-adee-fed42129a90b.png"></media:content><category>Grind75</category><description><![CDATA[<img src="https://img1.teletype.in/files/82/1f/821f5bcd-18ea-472a-9592-a135d9efa0e0.png"></img>Grind 75 - это набор из 75 задач по алгоритмам и структурам данных, которые рекомендуется решать для подготовки к техническим интервью в IT-компаниях. Эти задачи были собраны сообществом разработчиков и являются одним из наиболее популярных наборов задач для подготовки к техническим интервью.]]></description><content:encoded><![CDATA[
  <figure id="XVWw" class="m_original">
    <img src="https://img1.teletype.in/files/82/1f/821f5bcd-18ea-472a-9592-a135d9efa0e0.png" width="1000" />
  </figure>
  <p id="GK0G">Grind 75 - это набор из 75 задач по алгоритмам и структурам данных, которые рекомендуется решать для подготовки к техническим интервью в IT-компаниях. Эти задачи были собраны сообществом разработчиков и являются одним из наиболее популярных наборов задач для подготовки к техническим интервью.</p>
  <p id="Q4xo">Каждая статья будет посвящена решению одной задачи, которую мы будем разбирать на конкретных примерах и давать подробные объяснения каждого шага. Мы также будем обсуждать эффективность каждого алгоритма и его сложность.</p>
  <p id="ahGN">В этой статье мы начнем с первой задачи <a href="https://leetcode.com/problems/two-sum/" target="_blank">TwoSum</a>. Для начала попробуйте ее решить самостоятельно.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="ZpNh"><strong>Описание задачи:</strong></h2>
  </section>
  <p id="UyYM">На вход подается 2 параметра:</p>
  <p id="5sQ1">1) <code>nums</code> - массив целых чисел</p>
  <p id="q1Xr">2) <code>target</code> - искомое целое число</p>
  <p id="RCGa">Необходимо вернуть новый массив из 2-ух индексов массива <code>nums</code>, сумма чисел которых будет равняться искомому числу <code>target</code>.</p>
  <p id="3kJr">Примеры:</p>
  <pre id="f2st">Пример 1:
Параметры: nums = [2,7,11,15], target = 9
Результат: [0,1]
Пояснение: Потому что nums[0] + nums[1] == 9, мы возвращаем индексы [0, 1].</pre>
  <pre id="f2st">Пример 2:
Параметры: nums = [3,2,4], target = 6
Результат: [1,2]</pre>
  <pre id="wfsF">Пример 3:
Параметры: nums = [3,3], target = 6
Результат: [0,1]</pre>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="Leyx">Прямой метод решения</h2>
  </section>
  <p id="MV5e">Для решения данной задачи, мы используем два вложенных цикла. Внешний цикл перебирает все элементы массива <code>nums</code>, а внутренний цикл перебирает все оставшиеся элементы после i-го элемента. Таким образом, мы проверяем все возможные комбинации чисел в массиве.</p>
  <p id="xXEO">Объявим функцию <code>twoSum</code> и запишем два цикла внутри нее:</p>
  <figure id="dbcO" class="m_column">
    <img src="https://img4.teletype.in/files/7c/ea/7ceabe06-9980-42ae-ae08-b02188bba263.png" width="975" />
  </figure>
  <p id="ldaD">Прошу заметить, что <code>j</code> равняется <code>i + 1</code>, это было сделано для того, чтобы мы не брали в расчет элементы, которые остались слева от элемента <code>i</code>, потому что тогда мы будем проверять уже рассмотренные комбинации чисел, что не имеет смысла и может привести к повторным результатам.</p>
  <p id="NVfq">Теперь осталось проверить, что сумма чисел <code>i</code> и <code>j</code> будет равняться числу <code>target</code>, если это так, то мы вернем индексы этих элементов <code>[i, j]</code>:</p>
  <figure id="F62o" class="m_column">
    <img src="https://img2.teletype.in/files/5a/44/5a445496-0aa4-4320-a093-bab2313c2f78.png" width="967" />
  </figure>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="ILI7">Результат эффективности алгоритма</h2>
  </section>
  <p id="Q64m">Ответ принят, но скорость выполнения оставляет желать лучшего, попробуем оптимизировать наше решение.</p>
  <figure id="reEI" class="m_column">
    <img src="https://img3.teletype.in/files/27/44/2744dece-c92a-4e6c-8ac2-1324cc689544.png" width="1404" />
  </figure>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="F8gd">Метод решения со структурой хэш-таблица</h2>
  </section>
  <p id="Uu9k">Давайте попробуем избавиться от внутреннего цикла и используем хэш-таблицу для записи и быстрого доступа к элементам, что заметно даст нам прирост к эффективности выполнения программы.</p>
  <p id="ibJB">Алгоритм заключается в следующем:</p>
  <p id="uMgq">1. Создаем пустой объект <code>hash</code>.</p>
  <p id="kGrD">2. Проходим по всем элементам массива <code>nums</code> с помощью цикла <code>for</code>.</p>
  <p id="96Rk">3. Для каждого элемента <code>nums[i]</code> вычисляем число, которое нам нужно для сложения с элементом <code>nums[i]</code>, чтобы получить <code>target</code>, <code>sub = target - nums[i]</code>.</p>
  <p id="aKLS">Например: искомое число 10, элемент равен 7, следовательно <code>sub = 3</code>. В следующем шаге мы произведем проверку наличия <code>sub</code> в <code>hash</code>.</p>
  <p id="eTVc">4. Проверяем, есть ли значение <code>sub</code> в объекте <code>hash</code>. Если есть, значит мы нашли два числа, которые в сумме дают <code>target</code>, и возвращаем массив с индексами этих чисел <code>[i, hash[sub]]</code>.</p>
  <p id="YHc9">5. Если значение <code>sub</code> не найдено в объекте <code>hash</code>, то добавляем текущий элемент <code>nums[i]</code> и его индекс <code>i</code> в объект <code>hash</code>.</p>
  <p id="II3o">Теперь осталось написать алгоритм:</p>
  <figure id="CcPS" class="m_column">
    <img src="https://img1.teletype.in/files/89/1c/891cbf4b-cd08-4ef5-ae6c-a8336b1f784e.png" width="973" />
  </figure>
  <p id="APIt">Это решение имеет линейную сложность O(n), так как мы проходим по массиву только один раз. Использование хэш-таблицы позволяет нам ускорить поиск нужных значений до константного времени O(1).</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="ypds">Результат эффективности алгоритма</h2>
  </section>
  <p id="vnlK">Благодаря использованию хэш-таблицы, мы заметно ускорили наш алгоритм решения.</p>
  <figure id="TnYg" class="m_column">
    <img src="https://img1.teletype.in/files/43/90/4390a5e3-483d-479a-bb11-149b040c25b0.png" width="1388" />
  </figure>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="Uekc">Итог</h2>
  </section>
  <p id="Vt0P">Поздравляю, вы решили первую задачу из Grind 75.</p>
  <p id="RdBF">Подписывайтесь на <a href="https://t.me/days_on_front" target="_blank">канал</a>, чтобы не пропустить разбор следующих задач. Будем двигаться вместе на пути к улучшению своих навыков:)</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@dev.pologov/632HOjMyBRG</guid><link>https://teletype.in/@dev.pologov/632HOjMyBRG?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=dev.pologov</link><comments>https://teletype.in/@dev.pologov/632HOjMyBRG?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=dev.pologov#comments</comments><dc:creator>dev.pologov</dc:creator><title>Изящество и мощь: погружение в TypeScript Utility Types</title><pubDate>Tue, 09 Jan 2024 15:30:30 GMT</pubDate><media:content medium="image" url="https://img2.teletype.in/files/5b/e6/5be66372-b1e2-45c9-b003-700877107200.png"></media:content><category>TypeScript</category><description><![CDATA[<img src="https://img2.teletype.in/files/9e/d5/9ed5e165-ed68-45fb-a453-b87682bcdab7.png"></img>TypeScript предоставляет глобальные utility types, которые можно использовать для общий преобразований. В этой статье мы рассмотрим каждый из них с примером.]]></description><content:encoded><![CDATA[
  <figure id="kMve" class="m_original">
    <img src="https://img2.teletype.in/files/9e/d5/9ed5e165-ed68-45fb-a453-b87682bcdab7.png" width="1000" />
  </figure>
  <p id="ZXO8"><strong>TypeScript</strong> предоставляет глобальные utility types, которые можно использовать для общий преобразований. В этой статье мы рассмотрим большинство утилит с примерами.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="onBk">Awaited</h2>
  </section>
  <p id="3jXL"><code>Awaited&lt;Type&gt;</code> - Позволяет получить тип значения, возвращаемого асинхронной функцией. Он извлекает тип, который оборачивается в <code>Promise</code>, и позволяет описать тип значения, которое будет возвращено при разрешении этого <code>Promise</code>.</p>
  <figure id="BodP" class="m_column">
    <img src="https://img1.teletype.in/files/06/41/06416cdc-f5ba-4bf4-88d2-ac3db4d26937.png" width="1159" />
    <figcaption>Awaited</figcaption>
  </figure>
  <p id="7Ywi">Здесь тип <code>Awaited</code> используется для получения типа значения, которое будет возвращено при выполнении асинхронной функции <code>fetchUserData</code>.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="partialtype">Partial</h2>
  </section>
  <p id="7Was"><code>Partial&lt;Type&gt;</code> - Создает тип со всеми свойствами <code>Type</code>, которые становятся необязательными.</p>
  <figure id="dY4h" class="m_column">
    <img src="https://img2.teletype.in/files/d2/bb/d2bbe603-532c-4f5a-bc14-2e644306c6e9.png" width="1050" />
    <figcaption>Partial</figcaption>
  </figure>
  <p id="PoaA">В первом примере с объектом <code>user1</code>, компилятор выдаст ошибку из-за того, что мы не заполнили все свойства, которые указали в типе <code>User</code>.</p>
  <p id="9qQk">При использовании <code>Partial&lt;User&gt;</code> все свойства типа <code>User</code> стали необязательными.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="g3aL">Required</h2>
  </section>
  <p id="sqk8"><code>Required&lt;Type&gt;</code> - Устанавливает все свойства <code>Type</code> обязательными и работает противоположно утилите <code>Partial</code>.</p>
  <figure id="A6Ps" class="m_column">
    <img src="https://img3.teletype.in/files/e0/48/e048eec8-d361-485c-aa64-658f9f7c7fc4.png" width="995" />
    <figcaption>Required</figcaption>
  </figure>
  <p id="mbGH">Несмотря на то, что в типе <code>User</code> мы указали все свойства необязательными, мы использовали утилиту <code>Required</code>, которая преобразовала весь тип в обязательный, поэтому компилятор выдаст ошибку если мы не укажем все свойства в объекте.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="v8iM">Readonly</h2>
  </section>
  <p id="O29w"><code>Readonly&lt;Type&gt;</code> - Добавляет флаг <code>readonly</code> ко всем свойствам <code>Type</code>.</p>
  <figure id="bwmL" class="m_column">
    <img src="https://img3.teletype.in/files/ee/8c/ee8ce136-2f3a-4a8c-a9b9-5b077b472d61.png" width="1088" />
    <figcaption>Readonly</figcaption>
  </figure>
  <p id="Cwpa">Компилятор выдаст ошибку, потому что после преобразования утилитой <code>Readonly</code> все свойства типа <code>Todo</code> стали неизменяемыми.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="recordkeys-type">Record</h2>
  </section>
  <p id="poH3"><code>Record&lt;Keys, Type&gt;</code> - Создает объект, ключи которого являются <code>Keys</code>, а значения свойств <code>Type</code>.</p>
  <figure id="6mh1" class="m_column">
    <img src="https://img3.teletype.in/files/2d/cf/2dcff330-6b96-433c-93a1-b700899db2a1.png" width="972" />
    <figcaption>Record</figcaption>
  </figure>
  <p id="4W6H">В результате объект <code>dogs</code> будет содержать в себе ключи <code>DogName</code> и значения каждого ключа будут <code>age</code> и <code>weight</code>.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="xMor">Pick</h2>
  </section>
  <p id="VtJ7"><code>Pick&lt;Type, Keys&gt;</code> - Создает новый тип, содержащий только указанные свойства <code>Keys</code> из исходного типа <code>Type</code>.</p>
  <p id="sdc5">Например мы хотим создать объект только с именем и фамилией. Для этого мы будем использовать <code>Pick</code>, создадим новый тип <code>FullName</code> с этими свойствами.</p>
  <figure id="Bl8q" class="m_column">
    <img src="https://img1.teletype.in/files/43/fc/43fc54d3-f1b5-4824-a73d-1014e2bbfe49.png" width="976" />
    <figcaption>Pick</figcaption>
  </figure>
  <p id="psZr">Таким образом, <code>Pick</code> позволяет создавать новые типы, выбирая только необходимые свойства из исходного типа. Это может быть полезно, например, когда мы хотим передать только определенные свойства объекта в функцию или метод.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="lZ61">Omit</h2>
  </section>
  <p id="uwq4"><code>Omit&lt;Type, Keys&gt;</code> - Создает новый тип из полей <code>Type</code> без ключей <code>Keys</code>.</p>
  <figure id="8ObT" class="m_column">
    <img src="https://img4.teletype.in/files/b2/ec/b2ec7d9b-8837-4c52-967b-562e68e57d5b.png" width="1155" />
    <figcaption>Omit</figcaption>
  </figure>
  <p id="bYNk">В результате преобразований мы получили новый тип <code>Titles</code>, который содержит только <code>title</code> и <code>sub_title</code>.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="excludeuniontype-excludedmembers">Exclude</h2>
  </section>
  <p id="xscQ"><code>Exclude&lt;UnionType, ExcludedMembers&gt;</code> - Это тип, который исключает из объединения UnionType все типы, которые содержатся в ExcludedMembers.</p>
  <p id="9VhN">Например, если у нас есть объединение типов <code>MyUnion</code> и мы хотим исключить из него типы &quot;null&quot; и &quot;boolean&quot;, то мы можем использовать <code>Exclude</code> следующим образом:</p>
  <figure id="Zww7" class="m_column">
    <img src="https://img2.teletype.in/files/d8/41/d8414de1-ead2-408d-9df9-d08f116d661d.png" width="911" />
    <figcaption>Exclude</figcaption>
  </figure>
  <p id="NcKn">В результате получим новое объединение типов <code>MyNewUnion</code>, которое будет содержать только типы <code>string</code> и <code>number</code>.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="extracttype-union">Extract</h2>
  </section>
  <p id="RcS4"><code>Extract&lt;Type, Union&gt;</code> - Позволяет извлекать из объединения типов <code>Union</code> только те типы, которые являются подтипами <code>Type</code>.</p>
  <figure id="hiBM" class="m_column">
    <img src="https://img1.teletype.in/files/44/c3/44c3abc9-cb22-4ff7-984f-cd13455de42b.png" width="967" />
    <figcaption>Extract</figcaption>
  </figure>
  <p id="dxs1">В этом примере мы объявляем тип <code>MyUnion</code>, который представляет собой объединение типов <code>string</code>, <code>number</code> и <code>boolean</code>. Затем мы используем утилиту типов <code>Extract</code>, чтобы создать новый тип <code>MyStringOrNumber</code>, который содержит только типы <code>string</code> и <code>number</code> из объединения <code>MyUnion</code>.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="nonnullabletype">NonNullable</h2>
  </section>
  <p id="Rzmv"><code>NonNullable&lt;Type&gt;</code> - Позволяет создавать новый тип, который исключает значения <code>null</code> и <code>undefined</code> из типа <code>Type</code>.</p>
  <figure id="eD2p" class="m_column">
    <img src="https://img2.teletype.in/files/14/65/146597cb-8172-4bef-bec4-d15c3695b5da.png" width="967" />
    <figcaption>NonNullable</figcaption>
  </figure>
  <p id="viot">Мы объявляем тип <code>MyType</code>, который представляет собой объединение типов <code>string</code>, <code>null</code> и <code>undefined</code>. Затем мы используем утилиту типов <code>NonNullable</code>, чтобы создать новый тип <code>MyNonNullType</code>, который содержит только тип <code>string</code> без значений <code>null</code> и <code>undefined</code>.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="parameterstype">Parameters</h2>
  </section>
  <p id="8qVL"><code>Parameters&lt;Type&gt;</code> - Позволяет извлекать типы параметров функции в виде кортежа.</p>
  <figure id="Kjvd" class="m_column">
    <img src="https://img2.teletype.in/files/d2/2e/d22ea5c7-8b90-4db6-a2ad-5d9eac889818.png" width="1018" />
    <figcaption>Parameters</figcaption>
  </figure>
  <p id="UXLZ">Мы объявляем функцию <code>myFunction</code>, которая принимает три параметра разных типов. Затем мы используем утилиту типов <code>Parameters</code>, чтобы создать новый тип <code>MyFunctionParams</code>, который содержит типы параметров функции в виде кортежа.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="constructorparameterstype">ConstructorParameters</h2>
  </section>
  <p id="SwW3"><code>ConstructorParameters&lt;Type&gt;</code> - Позволяет извлекать типы параметров конструктора класса в виде кортежа.</p>
  <figure id="JsNX" class="m_column">
    <img src="https://img2.teletype.in/files/57/41/57415f78-30ae-4745-9731-51206ef5f338.png" width="1018" />
    <figcaption>ConstructorParameters</figcaption>
  </figure>
  <p id="CjLb">Мы объявляем класс <code>MyClass</code>, который имеет конструктор, принимающий три параметра разных типов. Затем мы используем утилиту типов <code>ConstructorParameters</code>, чтобы создать новый тип <code>MyClassParams</code>, который содержит типы параметров конструктора в виде кортежа.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="returntypetype">ReturnType</h2>
  </section>
  <p id="zBIX"><code>ReturnType&lt;Type&gt;</code> - Позволяет извлекать тип возвращаемого значения функции.</p>
  <figure id="BTtI" class="m_column">
    <img src="https://img3.teletype.in/files/a8/24/a824d8b0-9b99-4ed7-9503-dbb987727fc8.png" width="1009" />
    <figcaption>ReturnType</figcaption>
  </figure>
  <p id="bT8H">Мы объявляем функцию <code>myFunction</code>, которая возвращает строку. Затем мы используем утилиту типов <code>ReturnType</code>, чтобы создать новый тип <code>MyFunctionReturnType</code>, который содержит тип возвращаемого значения функции.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="gJrc">InstanceType</h2>
  </section>
  <p id="n3pq"><code>InstanceType&lt;Type&gt;</code> - Позволяет извлекать тип экземпляра класса.</p>
  <figure id="tIgg" class="m_column">
    <img src="https://img1.teletype.in/files/0b/3f/0b3f0eb6-31c8-4622-ad5d-5365d1bdce0a.png" width="1008" />
    <figcaption>InstanceType</figcaption>
  </figure>
  <p id="V3cY">Мы объявляем класс <code>MyClass</code>, который имеет свойство <code>name</code> и <code>конструктор</code>, который принимает строку и присваивает ее свойству name. Затем мы используем утилиту типов <code>InstanceType</code>, чтобы создать новый тип <code>MyInstanceType</code>, который содержит тип экземпляра класса.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="thisparametertypetype">ThisParameterType</h2>
  </section>
  <p id="Nk1i"><code>ThisParameterType&lt;Type&gt;</code> - Позволяет извлекать тип <code>this</code> из функции <code>Type</code>.</p>
  <figure id="8btY" class="m_column">
    <img src="https://img4.teletype.in/files/b4/39/b439149d-97f2-44ae-bd1f-bd027eb6212e.png" width="1004" />
    <figcaption>ThisParameterType</figcaption>
  </figure>
  <p id="jIiO">Мы объявили две функции:</p>
  <p id="vAvq">Первая функция - <code>toHex</code>, мы обозначили, что ее параметр <code>this</code> имеет тип <code>Number</code>.</p>
  <p id="b4rb">Вторая функция - <code>numberToString</code>, в параметрах с помощью <code>ThisParameterType</code> мы указали, что параметр <code>n</code> равняется <code>this</code> параметра функции <code>toHex</code>.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="omitthisparametertype">OmitThisParameter</h2>
  </section>
  <p id="HGa5"><code>OmitThisParameter&lt;Type&gt;</code> - Определяет функцию без типа <code>this</code>.</p>
  <figure id="Ey2J" class="m_column">
    <img src="https://img1.teletype.in/files/c7/c2/c7c2a580-10a7-4c95-8bbb-0845424382b6.png" width="1025" />
    <figcaption>OmitThisParameter</figcaption>
  </figure>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="thistypetype">ThisType&lt;Type&gt;</h2>
  </section>
  <p id="6TBr">Добавляет тип <code>this</code> к функции Type.</p>
  <figure id="7qUR" class="m_column">
    <img src="https://img2.teletype.in/files/5a/a8/5aa8f90c-fcf1-47da-b724-c5c732df3551.png" width="953" />
    <figcaption>ThisType</figcaption>
  </figure>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="7gpv">Заключение</h2>
  </section>
  <p id="2R7h">В данной статье мы рассмотрели почти все utility types, конечно, в реальной работе большинство из этого скорее всего вам не пригодится, но для справки и личного роста ознакомиться с существующими утилитами и возможностями TS будет круто. Знания данных утилит помогут вам все больше познавать TS и создавать умные типы для любой ситуации.</p>
  <p id="JTkc">Заглядывайте в мой телеграм канал - <a href="https://t.me/days_on_front" target="_blank">@days_on_front</a>, там будут другие интересные статьи по TS, фронту и разработке в целом.</p>
  <p id="6Vyh">Буду рад обратной связи. Спасибо за внимание!</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@dev.pologov/Oxe2u8hHWqK</guid><link>https://teletype.in/@dev.pologov/Oxe2u8hHWqK?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=dev.pologov</link><comments>https://teletype.in/@dev.pologov/Oxe2u8hHWqK?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=dev.pologov#comments</comments><dc:creator>dev.pologov</dc:creator><title>Docker, первые шаги.</title><pubDate>Tue, 02 Jan 2024 16:39:03 GMT</pubDate><media:content medium="image" url="https://img3.teletype.in/files/ed/af/edaf7bf2-ab5d-48ee-a88a-ffe491296c73.png"></media:content><description><![CDATA[<img src="https://img4.teletype.in/files/fc/07/fc07ecd3-d6c9-4160-9de9-e3117e423100.png"></img>В этой статье мы начнем делать первые шаги в изучении докера, особенно эта статья поможет junior/middle фронтенд разработчикам, которые хотят понять как работает докер и как за несколько простых шагов развернуть его на своей машине.]]></description><content:encoded><![CDATA[
  <figure id="zy9t" class="m_original">
    <img src="https://img4.teletype.in/files/fc/07/fc07ecd3-d6c9-4160-9de9-e3117e423100.png" width="1000" />
  </figure>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="Oz32">Введение</h2>
  </section>
  <p id="f5Pf">В этой статье мы начнем делать первые шаги в изучении докера, особенно эта статья поможет junior/middle фронтенд разработчикам, которые хотят понять как работает докер и как за несколько простых шагов развернуть его на своей машине.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="xflD">Какую проблему решает?</h2>
  </section>
  <p id="xf6M">Для запуска проектов мы используем большое количество сервисов:</p>
  <ul id="sjNy">
    <li id="goVN">pm2 или ts-node для запуска наших проектов на JS/TS</li>
    <li id="7Brx">Базы данных PostgreSQL, MySQL, MongoDB и т.д</li>
    <li id="kcXm">Веб-сервер nginx/apache</li>
    <li id="oVck">Мониторинговые системы</li>
    <li id="UciH">Redis или Memcache для кэширования данных</li>
    <li id="Nxyf">и другие полезные вещи</li>
  </ul>
  <p id="4YpS">Разворачивание такого большого количества сервисов на локальной машине всегда оборачивается болью, засорением памяти, конфликтом версий и танцами с бубном перед каждой сборкой проекта.</p>
  <p id="A4j8">В идеале хочется чтобы все зависимости разворачивались сами и были изолированы от операционной системы, чтобы на другой машине не приходилось ставить и поднимать все вручную. Данные проблемы решает контейнеризация.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="omIJ"><strong>Контейнеризация</strong></h2>
  </section>
  <p id="Xumw">Контейнеризация - это методология разработки и развертывания приложений, которая позволяет упаковать приложение и все его зависимости в единую единицу, называемую контейнером. Контейнер является изолированным окружением, которое содержит все необходимые компоненты для запуска приложения, включая библиотеки, фреймворки и настройки. Это облегчает процесс развертывания приложений, поскольку контейнер может быть запущен на любой машине, поддерживающей контейнеризацию, без необходимости установки или настройки зависимостей. Контейнеризация также обеспечивает высокую степень изоляции между приложениями, что уменьшает вероятность конфликтов и повышает безопасность.</p>
  <blockquote id="c6dx">Проще говоря - внутри вашей операционной системы запускается еще одна полностью изолированная операционная система, которую вы можете отключить отключить в любой момент времени. </blockquote>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="4goM">Docker</h2>
  </section>
  <p id="zhJO">Docker - это одна из платформ для контейнеризации приложений, которая позволяет разработчикам упаковывать приложения и их зависимости в контейнеры. Docker предоставляет инструменты для создания, управления и развертывания контейнеров, а так же для автоматизации процессов сборки и развертывания приложений.</p>
  <p id="ekOX">Инструкция по установке докера:</p>
  <ul id="bQA3">
    <li id="CBSO"><a href="https://docs.docker.com/desktop/install/mac-install/" target="_blank">Mac</a></li>
    <li id="POTS"><a href="https://docs.docker.com/desktop/install/windows-install/" target="_blank">Windows</a></li>
    <li id="MzOP"><a href="https://docs.docker.com/desktop/install/linux-install/" target="_blank">Ubuntu</a></li>
  </ul>
  <p id="tmHY">Шаги по развертыванию докера:</p>
  <ol id="qo04">
    <li id="gxLW">Описать настройки контейнера - операционную систему, программы, команды для запуска.</li>
    <li id="b8FZ">Собрать билд (build) контейнера из раннее описанных настроек.</li>
    <li id="63uJ">Запустить контейнер из созданного билда.</li>
  </ol>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="MiZZ">Поднимем наш первый контейнер</h2>
  </section>
  <p id="d2RL">Перейдем в папку и инициализируем проект.</p>
  <p id="vF0x"><code>npm init -y</code></p>
  <p id="C2sU">Будем использовать веб-сервер. Добавим express в проект.</p>
  <p id="TWZ8"><code>npm install express</code></p>
  <p id="OqOB">Создадим файл <code>index.js</code> и напишем простой код для веб-сервера.</p>
  <figure id="jIKR" class="m_column">
    <img src="https://img2.teletype.in/files/98/fb/98fb8353-622c-40d6-9643-f4c84c7d4652.png" width="1066" />
    <figcaption>index.js</figcaption>
  </figure>
  <p id="udXV">Напишем настройки для докер контейнера, для этого создадим файл в корне проекта <code>Dockerfile</code>.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="Z171">FROM</h2>
  </section>
  <p id="oS2I">Любой конечный <code>Dockerfile</code> называется образом. Для нашего контейнера нужна операционная система, в этом нам поможет команда <code>FROM</code>. Команда собирает контейнер из указанного образа операционной системы.  Докер поддерживает большинство доступных ОС, самые популярные из них это - Ubuntu, Debian. Синтаксис выглядит так:</p>
  <p id="bEJz"><code>FROM &lt;BASE&gt;:&lt;VERSION&gt;</code>, где BASE - название образа, а VERSION - версия.</p>
  <p id="bl2O">Добавим в наш файл следующую команду, скажем докеру, что мы хотим использовать образ <code>ubuntu:18.04</code> в нашем контейнере.</p>
  <figure id="sdZa" class="m_column">
    <img src="https://img2.teletype.in/files/dc/67/dc67345a-373e-4b23-99fe-32d677e2cae5.png" width="1047" />
    <figcaption>Dockerfile</figcaption>
  </figure>
  <p id="YAUU">Уже сейчас мы можем собрать билд контейнера. Перейдем в папку и введем команду <code>docker build -t server-app .</code></p>
  <p id="3DpH">Флаг <code>-t</code> позволяет нам указать имя нашего контейнера, а <code>.</code> говорит докеру где нужно искать <code>Dockerfile</code>. Докер найдет необходимый образ, скачает его и соберет наш билд. В консоли вы увидите что-то наподобие этого.</p>
  <figure id="SS6q" class="m_column">
    <img src="https://img4.teletype.in/files/34/69/3469319e-e49e-4586-9a95-3d6b3f2d2e53.png" width="2184" />
    <figcaption>terminal</figcaption>
  </figure>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="OjSk">RUN</h2>
  </section>
  <p id="WCmw">Мы добавили образ системы, но для запуска сервера на <code>express</code> нам необходимо установить <code>nodejs</code> и <code>npm</code> в нашу систему, для этого мы воспользуемся командой <code>RUN</code></p>
  <p id="RRf1">Добавим следующую строку в нашел образ.</p>
  <figure id="VK9j" class="m_column">
    <img src="https://img1.teletype.in/files/4a/b2/4ab2aeff-e928-4985-98a3-9ce0b921fadf.png" width="1011" />
    <figcaption>Dockerfile</figcaption>
  </figure>
  <p id="aqzZ">Синтаксис выглядит так - <code>RUN &lt;command&gt;</code>, где <code>command</code> означает любую валидную операцию в командой строке.</p>
  <p id="DLrO">Соберем образ еще раз.</p>
  <figure id="5wzT" class="m_column">
    <img src="https://img4.teletype.in/files/73/da/73da75a0-17af-4525-ad26-699d1414a95b.png" width="2082" />
    <figcaption>terminal</figcaption>
  </figure>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="eOhY">COPY / WORKDIR</h2>
  </section>
  <p id="4o1t">Наш контейнер ничего не знает о сервере написанном в файле <code>index.js</code>, чтобы мы смогли запустить сервер, нам нужно скопировать файлы в наш контейнер. Для этого воспользуемся командой <code>WORKDIR</code>, чтобы указать рабочий каталог на который будут указывать все остальные команды по типу <code>RUN</code>, <code>CMD</code>, <code>ENTRYPOINT</code>, <code>COPY и ADD.</code></p>
  <p id="gZRZ">Синтаксис команды выглядит так: <code>WORKDIR &lt;PATH&gt;, </code>где <code>PATH</code> - это путь до каталога.</p>
  <p id="PtNr">Теперь воспользуемся командой <code>COPY</code> и скопируем файлы проекта в контейнер. Синтаксис: <code>COPY &lt;HOME_PATH&gt;:&lt;WORK_PATH&gt;</code>, где <code>HOME_PATH</code> - это путь до файла/папки, а <code>WORK_PATH</code> - это путь до места, куда мы хотим скопировать файлы.</p>
  <p id="wpKO">Добавим в наш образ следующие строки:</p>
  <figure id="z4Ow" class="m_column">
    <img src="https://img4.teletype.in/files/b9/23/b92306f8-8170-492a-8232-9594494d0556.png" width="1029" />
    <figcaption>Dockerfile</figcaption>
  </figure>
  <p id="NDYJ">Во-первых мы указали что путь <code>/var/www</code> является нашим корневым каталогом в контейнере.</p>
  <p id="PdlE">Во-вторых указали, что хотим скопировать файл <code>index.js</code> в файл с названием <code>index.js</code>, т.к мы уже указали рабочий каталог, то он будет скопирован в папку <code>/var/www</code></p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="LfL3">CMD</h2>
  </section>
  <p id="fERg">Попробуем запустить контейнер и посмотреть что мы успешно скопировали файл. Для этого воспользуемся командой CMD. Она будет выполняться после запуска контейнера и может быть только одна для всего докерфайла.</p>
  <p id="wLj5">Синтаксис следующий: <code>CMD [&lt;COMMAND&gt;, &lt;PARAM_1&gt;, &lt;PARAM_N&gt;]</code>, где <code>COMMAND</code> - название команды, <code>PARAM_N</code> - передаваемые параметры.</p>
  <p id="3XFN">Добавим команду:</p>
  <figure id="skzH" class="m_column">
    <img src="https://img2.teletype.in/files/52/80/5280b9a8-97fd-430d-9f5c-6a23c741f114.png" width="1032" />
    <figcaption>Dockerfile</figcaption>
  </figure>
  <p id="oBBE">Соберем контейнер <code>docker build -t server-app .</code> и запустим контейнер <code>docker run server-app</code></p>
  <p id="R528">В результате вы должны увидеть название нашего файла:</p>
  <figure id="l6EV" class="m_column">
    <img src="https://img1.teletype.in/files/4c/e1/4ce1cee1-f6c8-470a-8c31-d0b1245efb0e.png" width="1104" />
    <figcaption>terminal</figcaption>
  </figure>
  <p id="vE1S">Файл с сервером успешно скопирован в контейнер, осталось его запустить, но перед этим нам нужно установить зависимости из <code>package.json</code>, для этого немного изменим путь, скопировав всю папку с проектом целиком, а не только один <code>index.js</code>, потом добавим команду <code>RUN</code> для установки зависимостей и запустим сервер с помощью <code>CMD:</code></p>
  <figure id="uPZ8" class="m_column">
    <img src="https://img3.teletype.in/files/64/42/64428fe2-b9af-4c1e-9793-5d0e8c8a7a21.png" width="1021" />
    <figcaption>Dockerfile</figcaption>
  </figure>
  <p id="sLQx">Соберем образ и запустим:</p>
  <figure id="WlSN" class="m_column">
    <img src="https://img2.teletype.in/files/5c/5e/5c5ef59f-c7c2-4aa9-a179-628fb4e4f4d9.png" width="1024" />
    <figcaption>terminal</figcaption>
  </figure>
  <p id="OvbK"><strong>Поздравляю, наш сервер запущен в контейнере!</strong></p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="Tz3H">Запуск Docker&#x27;а в фоновом процессе, остановка и мониторинг.</h2>
  </section>
  <p id="34Fb">Для запуска в фоновом режиме воспользуемся флагом -d. Запустим наш контейнер.</p>
  <figure id="n1hn" class="m_column">
    <img src="https://img3.teletype.in/files/2c/76/2c76a715-ff62-4baf-9f31-c3cfe66b693f.png" width="1182" />
    <figcaption>terminal</figcaption>
  </figure>
  <p id="OELm">В ответе мы видим название контейнера работающего в фоне. Введите <code>docker ps</code> для того чтобы увидеть все запущенные контейнеры.</p>
  <figure id="YNnM" class="m_column">
    <img src="https://img4.teletype.in/files/fe/6e/fe6e39d1-cb38-41ef-9544-bb38c195d105.png" width="2070" />
    <figcaption>terminal</figcaption>
  </figure>
  <p id="lrM7">Для остановки контейнера напишите <code>docker stop -t 0 &lt;CONTAINER_ID&gt;</code>, где  флаг <code>-t 0</code> - говорит докеру немедленно остановить контейнер, а<code>CONTAINER_ID</code> - первые несколько символов названия контейнера.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="zT9q">Проброс портов</h2>
  </section>
  <p id="x4qw">Теперь попробуем зайти на localhost:3003 и получаем ошибку, почему? Потому что все что запускается внутри контейнера - остается внутри контейнера и наша хост машина ничего не знает о нем.</p>
  <p id="cJ2n">Для того чтобы что смогли получить доступ - нам нужно пробросить порт снаружи в контейнер. Команда <code>EXPOSE</code> добавляет информацию о порте для пользователя <code>Dockerfile</code> и несет только информационный характер. Для настоящего проброса при запуске контейнера нужно напрямую передать ему порт хоста и порт контейнера.</p>
  <p id="bKG3">Синтаксис: <code>-p &lt;HOST_PORT&gt;:&lt;CONTAINER_PORT&gt;</code></p>
  <p id="rBEn">Добавим <code>EXPOSE &lt;PORT&gt;</code> в <code>Dockerfile</code></p>
  <figure id="bsYS" class="m_column">
    <img src="https://img1.teletype.in/files/8a/23/8a2316e5-b055-4cd6-9dbd-929b2007e378.png" width="999" />
    <figcaption>Dockerfile</figcaption>
  </figure>
  <p id="mpD5">Соберем контейнер и запустим с помощью команды <code>docker run -d -p 4000:3003 server-app</code></p>
  <p id="guYV">Попробуйте перейти по адресу localhost:4000, поздравляю, сервер нам ответил.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="y7PO">Проброс файлов</h2>
  </section>
  <p id="EShk">Все, что запускается внутри контейнера - останется внутри контейнера при его остановки, поэтому держать файлы вроде базы данных нецелесообразно, потому что каждый раз после остановки - файлы будут стираться. Для таких случаев можно воспользоваться пробросом файлов в контейнер с хост машины. </p>
  <p id="Gxun">Давайте создадим папку <code>shared</code> на уровень ниже относительно <code>Dockerfile</code>, чтобы при билде докер не подхватил его тоже, и внутрь папки поместим файл <code>text.json</code>.</p>
  <p id="u5QE">Изменим наш <code>index.js</code> добавив отправку файла из папки shared.</p>
  <figure id="NWWF" class="m_column">
    <img src="https://img2.teletype.in/files/d9/04/d904b140-2e49-4679-b35d-43c7d4bead06.png" width="1023" />
    <figcaption>index.js</figcaption>
  </figure>
  <p id="D3dc">Теперь соберем контейнер <code>docker build -t server-app .</code> и запустим его добавив новый флаг <code>-v &lt;HOST_ABSOLUTE_PATH&gt;:&lt;CONTAINER_ABSOLUTE_PATH&gt;</code>, где указываем абсолютный путь до папки и конечный путь внутри контейнера, команда запуска будет такой:</p>
  <p id="PBb6"><code>docker run -d -p 4000:3003 -v /Users/username/shared:/var/www/shared server-app</code></p>
  <p id="0uQe">Попробуем перейти по <code>localhost:4000</code> и видим что сервер прислал содержимое файла <code>text.json</code>, который мы пробросили в контейнер. Попробуйте изменить <code>text.json</code> и обновите страницу, вы увидите что контент так же изменился без сборки и перезапуска контейнера.</p>
  <p id="uos7">Проброс файловой системы применяют тогда, когда данные контейнера надо сохранить. Для этого выясняют, где в контейнере приложение хранит свои данные, и пробрасывают туда локальную папку из проекта. Содержимое пробрасываемых папок обязательно добавляют в <code>.gitignore</code>, оставляя в них только файл <code>.gitkeep</code>, чтобы не возникло приключений с отсутствующими папками (попробуйте прокинуть в контейнер папку, которой не существует на хосте, будет ошибка).</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <h2 id="wBdM">Заключение</h2>
  </section>
  <p id="Qzn6">В данной статье мы изучили базовые команды, научились собирать, запускать и останавливать контейнер, поняли как пробрасывать порты и файлы. Данная статья погрузила в мир докера, но постоянно делать одни и те же действия в виде сборки и запуска из командой строки не очень удобно. Скоро мы расскажем про Docker Compose, который значительно облегчит вашу жизнь, а пока подписывайтесь на наш <a href="https://t.me/days_on_front" target="_blank">телеграмм канал</a>.</p>
  <p id="KCqX">Спасибо за внимание. Буду рад обратной связи:)</p>

]]></content:encoded></item></channel></rss>