<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Savvas Stephanides</title>
    <description>The latest articles on Forem by Savvas Stephanides (@savvasstephnds).</description>
    <link>https://forem.com/savvasstephnds</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F442868%2F6a2136ec-8eab-41a5-8c67-b1f65113f6e8.jpg</url>
      <title>Forem: Savvas Stephanides</title>
      <link>https://forem.com/savvasstephnds</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/savvasstephnds"/>
    <language>en</language>
    <item>
      <title>Run Deepseek locally using Docker!</title>
      <dc:creator>Savvas Stephanides</dc:creator>
      <pubDate>Mon, 10 Feb 2025 16:52:33 +0000</pubDate>
      <link>https://forem.com/savvasstephnds/run-deepseek-locally-using-docker-2pdm</link>
      <guid>https://forem.com/savvasstephnds/run-deepseek-locally-using-docker-2pdm</guid>
      <description>&lt;h2&gt;
  
  
  About
&lt;/h2&gt;

&lt;p&gt;If you follow AI news even a little bit, you've probably heard of Deepseek. The new AI app built in China which is supposed to be a lot better than anything else out there. You've also probably heard horror stories about apps from China collecting information on their users.&lt;/p&gt;

&lt;p&gt;If this sounds like you, you're probably looking for a better alternative. And there is: You can build a Deepseek client on your local system and run it without any access to the Internet. What's even better is that you can do this in Docker so you don't need anything else installed. Sound good? If yes, read on!&lt;/p&gt;

&lt;h2&gt;
  
  
  What we're building
&lt;/h2&gt;

&lt;p&gt;We're going to use Docker to create a web interface where you can ask questions to Deepseek. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;📖 &lt;a href="https://savvas.me/explained/docker" rel="noopener noreferrer"&gt;Docker, explained&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To do this, we're going to create two apps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A Deepseek endpoint built with Ollama&lt;/li&gt;
&lt;li&gt;A simple static website which calls the endpoint and gets answers to questions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When we're building multiple apps that communicate with each other, we can do this easily in Docker using &lt;strong&gt;Docker Compose&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;p&gt;🏃‍♂️ &lt;strong&gt;In a hurry?&lt;/strong&gt; Just &lt;a href="https://github.com/SavvasStephanides/local-deepseek" rel="noopener noreferrer"&gt;clone this repository&lt;/a&gt; and follow the instructions in the README file!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create docker-compose file
&lt;/h3&gt;

&lt;p&gt;To work with Docker Compose, we first need to create a new file in our project's directory. Create a new directory for your project if you haven't do so already and in that, create a new file called &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;💡 A docker-compose.yml file is the place where we will be describing our two apps so we can run them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Add first app
&lt;/h3&gt;

&lt;p&gt;Now that we created our Docker Compose file, let's define our first app, the Deepseek Ollama app. In Docker Compose, apps are called "services", but it's essentially the same thing. &lt;/p&gt;

&lt;p&gt;The Deepseek Ollama app is where we're going to point to to ask questions to Deepseek and get answers.&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;What is Ollama?&lt;/strong&gt; &lt;a href="https://www.ollama.com/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; is a lightweight framework where you can easily run open source frameworks, like Deepseek or Llama, on your computer locally. &lt;/p&gt;

&lt;p&gt;To add the Deepseek endpoint to your &lt;code&gt;docker-compose.yml&lt;/code&gt; file, add this to the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ollama&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ollama/ollama&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./ollama-models:/root/.ollama&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;11434:11434&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🤔 What is going on here?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This part tells Docker Compose to create a container called "ollama" &lt;/li&gt;
&lt;li&gt;The container will be based on the image (basically a blueprint) called &lt;code&gt;ollama/ollama&lt;/code&gt;. This is an image which comes with Ollama preinstalled so you don't have to do anything else!&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;volumes&lt;/code&gt; part essentially saves all the data from the models we're going to install later on your local hard drive. Within the container, all this data is saved in &lt;code&gt;/root/.ollama&lt;/code&gt; but will disappear once the container is shut down. Not exactly what we want. So whatever is stored in the container's directory, will be permanently stored in &lt;code&gt;ollama-models&lt;/code&gt; directory in your project's root.&lt;/li&gt;
&lt;li&gt;When the Ollama app gets up and running, it will run on the &lt;code&gt;11434&lt;/code&gt; port within the container, but not on your machine, which means you won't be able to access it from your browser. To fix this, the &lt;code&gt;ports&lt;/code&gt; part pairs the two ports.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we added the Ollama endpoint, we can now run it so we can install Deepseek. To do this, just run this Docker Compose command in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt; ollama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now go to your browser and check that the Ollama app is running, by pointing your browser to this address:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://localhost:11434" rel="noopener noreferrer"&gt;http://localhost:11434&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your browser should show the "Ollama is running" text like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fay3ravbwg3s79yjq9f1u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fay3ravbwg3s79yjq9f1u.png" alt="A browser window with " width="800" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Install Deepseek
&lt;/h3&gt;

&lt;p&gt;Now that Ollama is up and running, we can now go ahead and install our Deepseek model. To do this just run this Docker Compose command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nb"&gt;exec &lt;/span&gt;ollama ollama pull deepseek-r1:7b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🤔 &lt;strong&gt;What is going on here?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;exec&lt;/code&gt; command from Docker Compose essentially runs any command within a given container, in this case the &lt;code&gt;ollama&lt;/code&gt; container. The above line runs (executes) the command &lt;code&gt;ollama pull deepseek-r1:7b&lt;/code&gt; which installs the Deepseek model. The basic structure of the &lt;code&gt;exec&lt;/code&gt; command is as follows: &lt;code&gt;docker compose exec &amp;lt;containerName&amp;gt; &amp;lt;command&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This command will take a few minutes to install (depending on the size of the model) but once this is done, it should populate the new &lt;code&gt;ollama-models&lt;/code&gt; directory with the files needed for the Deepseek model.&lt;/p&gt;

&lt;p&gt;💡 The Deepseek model comes in lots of different sizes. For this example, I've chosen 7b (which means 7 billion parameters) but you can choose more or less depending on the capabilities of your system. You can see the &lt;a href="https://www.ollama.com/library/deepseek-r1" rel="noopener noreferrer"&gt;full list here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Create a website
&lt;/h3&gt;

&lt;p&gt;Now that we have our Deepseek app up and running, we can create a web interface to ask questions. We're going to create a simple site with HTML, CSS and Javascript. This is what we're creating:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyzwjs2q06f3ri5nw6mkf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyzwjs2q06f3ri5nw6mkf.png" alt="Screenshot of the website" width="677" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here's how:&lt;/p&gt;

&lt;h4&gt;
  
  
  HTML
&lt;/h4&gt;

&lt;p&gt;The HTML is going to define a simple page with a text box, a button to send the question and a space for the answer. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;📖 &lt;a href="https://savvas.me/explained/html" rel="noopener noreferrer"&gt;HTML, explained&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Create a new directory called &lt;code&gt;web&lt;/code&gt; and inside that create a new file called &lt;code&gt;index.html&lt;/code&gt;. Paste this HTML inside the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My AI&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"showdown.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"ollama.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"style.css"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;🤖 Local Deepseek&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"question"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;"run()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Ask!&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"answer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🤔 &lt;strong&gt;What is going on here?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; part of the HTML, you'll notice that we're linking to a &lt;code&gt;style.css&lt;/code&gt; We'll create this file next in order to style our website.&lt;/li&gt;
&lt;li&gt;You'll also notice two Javascript files, &lt;code&gt;ollama.js&lt;/code&gt; and &lt;code&gt;showdown.min.js&lt;/code&gt;. &lt;code&gt;ollama.js&lt;/code&gt; will be where we talk to Deepseek and &lt;code&gt;showdown.min.js&lt;/code&gt; uses Showdown, a Javascript library for converting Markdown (what we'll be getting back from Deepseek) to HTML.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  CSS
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;📖 &lt;a href="https://savvas.me/explained/css" rel="noopener noreferrer"&gt;CSS, explained&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To style our page, create a new file called &lt;code&gt;style.css&lt;/code&gt; and paste the CSS below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;600px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;#question&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;#answer&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Helvetica&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;#answer&lt;/span&gt; &lt;span class="nf"&gt;#think&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#eee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#aaa&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;italic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Javascript
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;📖 &lt;a href="https://savvas.me/explained/javascript" rel="noopener noreferrer"&gt;Javascript, explained&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now we're going to create the Javascript to talk to Deepseek and give us answers to our questions. Create a new file called &lt;code&gt;ollama.js&lt;/code&gt; and paste this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;converter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;showdown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Converter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#question&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:11434/api/generate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deepseek-r1:7b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getReader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextDecoder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;compiledResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;decoder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;chunkJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;compiledResponse&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;chunkJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;
        &lt;span class="nx"&gt;compiledResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;compiledResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;think&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;div id="think"&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;compiledResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;compiledResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/think&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#answer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;converter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;compiledResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🤔 &lt;strong&gt;What is going on here?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We're creating a Javascript function called &lt;code&gt;run()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Within the function, we're going to get the text from the text box in our HTML using &lt;code&gt;document.querySelector("#question").value&lt;/code&gt; and store it in a variable called &lt;code&gt;prompt&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Then we're going to use the built in &lt;code&gt;fetch()&lt;/code&gt; function to send a &lt;code&gt;POST&lt;/code&gt; request to &lt;code&gt;http://localhost:11434/api/generate&lt;/code&gt; which includes our prompt. The response is stored in a variable called &lt;code&gt;response&lt;/code&gt;. Since we've set &lt;code&gt;stream: true&lt;/code&gt;, we're going to get a response in small chunks.&lt;/li&gt;
&lt;li&gt;To get each chunk individually, we're going to run &lt;code&gt;response.body.getReader()&lt;/code&gt; to get the reader and initialise a new &lt;code&gt;TextDecoder&lt;/code&gt; with &lt;code&gt;new TextDecoder()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We're introducing a new empty string &lt;code&gt;let entireResponse = ""&lt;/code&gt; which we're going to be appending each chunk of the response.&lt;/li&gt;
&lt;li&gt;Finally, the &lt;code&gt;while&lt;/code&gt; loop is going to run until it runs out of chunks. For each chunk, we're going to get the response, add it to the &lt;code&gt;entireResponse&lt;/code&gt;, process it, and show it to the webpage using &lt;code&gt;document.querySelector("#answer").innerHTML = entireResponseAsHtml&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🤔 Why are we processing the response?&lt;/p&gt;

&lt;p&gt;The response comes back from Deepseek looking like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;think&amp;gt;&lt;/span&gt;
The user says hello so I should say hello back
&lt;span class="nt"&gt;&amp;lt;/think&amp;gt;&lt;/span&gt;

&lt;span class="gs"&gt;**Hello! How are you doing?**&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we process the file, we replace &lt;code&gt;&amp;lt;think&amp;gt;&lt;/code&gt; with &lt;code&gt;&amp;lt;div id="think"&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;/think&amp;gt;&lt;/code&gt; with &lt;code&gt;&amp;lt;/div&amp;gt;&lt;/code&gt;. This way we can style it however we like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;entireResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;entireResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;think&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;div id="think"&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;entireResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;entireResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/think&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're also then converting the entire response from Markdown into HTML, using the ShowdownJS library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;entireResponseAsHtml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;converter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entireResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Import showdown
&lt;/h4&gt;

&lt;p&gt;Finally, we need to add ShowdownJS to our project. To do this, simply &lt;a href="https://cdnjs.cloudflare.com/ajax/libs/showdown/2.1.0/showdown.min.js" rel="noopener noreferrer"&gt;download this file&lt;/a&gt; and add it to the &lt;code&gt;web&lt;/code&gt; directory of your project.&lt;/p&gt;

&lt;p&gt;At the end of all this, the &lt;code&gt;web&lt;/code&gt; directory should look like this:&lt;/p&gt;

&lt;p&gt;📝 index.html&lt;br&gt;
📝 ollama.js&lt;br&gt;
📝 showdown.min.js&lt;br&gt;
📝 style.css&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 5: Add web page to Docker Compose
&lt;/h3&gt;

&lt;p&gt;Once you're done with the creation of your website, add your app to the Docker Compose file like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:1.27.3-alpine&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./web:/usr/share/nginx/html&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3001:80"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your entire &lt;code&gt;docker-compose.yml&lt;/code&gt; file should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ollama&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ollama/ollama&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./ollama-models:/root/.ollama&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;11434:11434&lt;/span&gt;

  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:1.27.3-alpine&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./web:/usr/share/nginx/html&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3001:80"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run the website
&lt;/h3&gt;

&lt;p&gt;Now that we've created our website and added to our &lt;code&gt;docker-compose.yml&lt;/code&gt; file, we can run it with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt; web
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Give it one or two seconds and then point your browser to this URL:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://localhost:3001" rel="noopener noreferrer"&gt;http://localhost:3001&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you see this, we're good to go:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44x3yt14hyf95qxhlx4e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44x3yt14hyf95qxhlx4e.png" alt="Website screenshot" width="800" height="622"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's test it!
&lt;/h2&gt;

&lt;p&gt;Let's give our AI app a go! Write a question in the text box and click the Ask button.&lt;/p&gt;

&lt;p&gt;Deepseek should soon start responding. First with some "thinking"...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp41t84kv7pb545eiewrj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp41t84kv7pb545eiewrj.png" alt="The thinking box" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funcpvskyn6uko2weiqeq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funcpvskyn6uko2weiqeq.png" alt="The answer box" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how it looks on Video:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/1055265664" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;And that's it! You are now running Deepseek locally using just Docker!&lt;/p&gt;

&lt;p&gt;Now every time you want to run your AI app, just run this command from your project directory in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it!&lt;/p&gt;

&lt;p&gt;Any questions? Let me know here!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>deepseek</category>
      <category>ai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Host PHP for free!</title>
      <dc:creator>Savvas Stephanides</dc:creator>
      <pubDate>Wed, 02 Oct 2024 12:09:27 +0000</pubDate>
      <link>https://forem.com/savvasstephnds/host-php-for-free-iig</link>
      <guid>https://forem.com/savvasstephnds/host-php-for-free-iig</guid>
      <description>&lt;p&gt;PHP was and remains one of the most popular web application languages out there. However, the choices for hosting a PHP project for free are limited, especially with services like 000webhost shutting down.&lt;/p&gt;

&lt;p&gt;Fear not however... You can host your PHP project for free on Render using Docker! &lt;/p&gt;

&lt;p&gt;💡 &lt;a href="https://savvas.me/explained/docker" rel="noopener noreferrer"&gt;Docker, explained&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's how:&lt;/p&gt;

&lt;h2&gt;
  
  
  What you'll need to have installed
&lt;/h2&gt;

&lt;p&gt;Before we begin, make sure you have Docker installed on your machine. &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;Install Docker&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;h3&gt;
  
  
   Step 1: Create a PHP project
&lt;/h3&gt;

&lt;p&gt;Firstly, we'll going to create a simple PHP project with a simple "Hello world" message:&lt;/p&gt;

&lt;p&gt;Create a new directory &lt;code&gt;myPhpProject&lt;/code&gt; and point to the directory using your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;myPhpProject
&lt;span class="nb"&gt;cd &lt;/span&gt;myPhpProject
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we're going to create our web page. Create a file called  &lt;code&gt;index.php&lt;/code&gt; using either your terminal or your favourite code editor.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;index.php&lt;/code&gt; file add this PHP code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello world"&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 &lt;strong&gt;What does this code do?&lt;/strong&gt; This code opens a "code block" to write PHP code using &lt;code&gt;&amp;lt;?php&lt;/code&gt; and &lt;code&gt;?&amp;gt;&lt;/code&gt;. We can write our PHP code inside it. Then we use the &lt;code&gt;echo&lt;/code&gt; keyword from PHP to write something on the page. In this case, "Hello world".&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create a Docker Hub account
&lt;/h3&gt;

&lt;p&gt;Now let's take a few seconds to set up a free account on Docker Hub. &lt;a href="https://app.docker.com/signup" rel="noopener noreferrer"&gt;Sign up for Docker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But why? Because in the next steps, we're going to create an image from our PHP project and publish it on Docker Hub. Docker Hub is just a library of pre-existing images like Ubuntu, Python or NodeJS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkvjnbbzefhsekhxjalvm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkvjnbbzefhsekhxjalvm.png" width="800" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Create a Docker image
&lt;/h3&gt;

&lt;p&gt;Now we're going to create our Docker image. Go ahead and create a file called &lt;code&gt;Dockerfile&lt;/code&gt; in your app directory.&lt;/p&gt;

&lt;p&gt;What's a &lt;code&gt;Dockerfile&lt;/code&gt;? A &lt;code&gt;Dockerfile&lt;/code&gt; is a file which gives instructions to Docker on how to create an image.&lt;/p&gt;

&lt;p&gt;Add this to your &lt;code&gt;Dockerfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; php:7.4-apache&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./index.php /var/www/html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 &lt;strong&gt;What does this do?&lt;/strong&gt; Firstly, it gets a pre-existing handy image from Docker Hub which has PHP and Apache already installed. Next it copies the &lt;code&gt;index.php&lt;/code&gt; file we created earlier into the &lt;code&gt;html&lt;/code&gt; directory. This is where Apache will grab the file and show it to the browser.&lt;/p&gt;

&lt;p&gt;Now that we created our &lt;code&gt;Dockerfile&lt;/code&gt;, it's time to create our image. Run this command in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; myphpproject &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What does this do? It just tells Docker to grab the &lt;code&gt;Dockerfile&lt;/code&gt;, create an image from it and call it &lt;code&gt;myphpproject&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now that we created our image, let's test it out by running a container from it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 80:80 myphpproject
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 What does this do? It uses our new image, &lt;code&gt;myphpproject&lt;/code&gt; to create a container which contains our website. The website will be available from port 80, so after a few seconds you can access it from here:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://localhost" rel="noopener noreferrer"&gt;http://localhost&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Host image on Docker Hub
&lt;/h3&gt;

&lt;p&gt;Now that our image is ready, it's time to host it to Docker Hub.&lt;/p&gt;

&lt;p&gt;Firstly, login to Docker Hub from your Terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The process should look a bit like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Username: savvasstephanides
Password: 
Login Succeeded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we need to give our image a tag. Sort of like a version number:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker tag myphpproject savvasstephanides/myphpproject:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can iterate your version numbers for each new version.&lt;/p&gt;

&lt;p&gt;Now that our image and tag are ready, we can push our image to Docker Hub, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker push savvasstephanides/myphpproject:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your terminal should look a bit like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The push refers to repository [docker.io/savvasstephanides/myphpproject]
93b8f571dc38: Pushed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now log in to Docker Hub in your browser and check out your image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg1yafsds9w73kgxrparj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg1yafsds9w73kgxrparj.png" width="709" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Sign up for Render
&lt;/h3&gt;

&lt;p&gt;Render is a great service that lets you host your projects with a generous free tier. Go ahead and &lt;a href="https://dashboard.render.com/register" rel="noopener noreferrer"&gt;sign up for Render for free&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52dfhtiwzs240g2kpduf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52dfhtiwzs240g2kpduf.png" width="709" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a new Web service on Render
&lt;/h3&gt;

&lt;p&gt;After signing up to Render, go to the Dashboard.&lt;/p&gt;

&lt;p&gt;From the Dashoard, select New and then Web service:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnl779h3otgh3gpgpgzvn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnl779h3otgh3gpgpgzvn.png" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, choose &lt;em&gt;Existing image&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6mmeathk113qxmpd4qkh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6mmeathk113qxmpd4qkh.png" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under Image URL, write the address of your image like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker.io/&amp;lt;your_docker_hub_username&amp;gt;/&amp;lt;project_name&amp;gt;:&amp;lt;tag_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker.io/savvasstephanides/myphpproject:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Give your project a name:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw92j78vyqvjq65t9zov9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw92j78vyqvjq65t9zov9.png" width="715" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select &lt;em&gt;Free&lt;/em&gt; under Instance type:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv568vuibd3dp48enwdw4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv568vuibd3dp48enwdw4.png" width="800" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click Deploy Web Service:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbscnog236gdv6k5mpwb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbscnog236gdv6k5mpwb.png" width="800" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Give it a few seconds to complete:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxiiorp3i182f53eqqaon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxiiorp3i182f53eqqaon.png" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once it's done...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxe28js23cr2g8y2n4pad.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxe28js23cr2g8y2n4pad.png" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the link at the top left that looks like &lt;code&gt;https://abc.onrender.com&lt;/code&gt;. Your website is up and running! &lt;br&gt;
🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftznlgyj6zckpz4g6a7ih.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftznlgyj6zckpz4g6a7ih.png" width="800" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You've successfully published your PHP app online!&lt;/p&gt;

&lt;p&gt;Have you hosted your PHP using this tutorial? Paste a link to your project in the comments to show off your creations! Thanks for reading!&lt;/p&gt;

</description>
      <category>php</category>
      <category>docker</category>
      <category>webdev</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Create a new Laravel project in seconds using Docker!</title>
      <dc:creator>Savvas Stephanides</dc:creator>
      <pubDate>Thu, 12 Sep 2024 16:53:47 +0000</pubDate>
      <link>https://forem.com/savvasstephnds/create-a-new-laravel-project-in-seconds-using-docker-n9c</link>
      <guid>https://forem.com/savvasstephnds/create-a-new-laravel-project-in-seconds-using-docker-n9c</guid>
      <description>&lt;p&gt;Docker makes getting started with a new projects much easier, saving you hours of setting up individual tools for it to work. Laravel is no exception. Here's how you can set up a new Laravel project using &lt;a href="https://savvas.me/explained/docker" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;, complete with a MySQL database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create a new project directory
&lt;/h2&gt;

&lt;p&gt;First, we're going to set up a new empty directory, which will be houising our Laravel project. Call it &lt;code&gt;myApp&lt;/code&gt; or whatever else you like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;myApp
&lt;span class="nb"&gt;cd &lt;/span&gt;myApp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Create a Docker Compose file
&lt;/h2&gt;

&lt;p&gt;Next we're going to define our two containers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;One for our Laravel project which will container all the PHP code necessary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One for the MySQL database. If you'd rather use MariaDB, replace &lt;code&gt;image: mysql:8.0&lt;/code&gt; with &lt;code&gt;image: mariadb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bitnami/laravel&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./app:/app&lt;/span&gt;
    &lt;span class="na"&gt;working_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/app&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;LARAVEL_DATABASE_HOST=db&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;LARAVEL_DATABASE_USER=root&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;LARAVEL_DATABASE_NAME=laravel&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;LARAVEL_DATABASE_PASSWORD=pass1&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;LARAVEL_DATABASE_PORT_NUMBER=3306&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8000:8000&lt;/span&gt;

  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql:8.0&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MYSQL_ROOT_PASSWORD=pass1&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MYSQL_DATABASE=laravel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What is happening here?
&lt;/h3&gt;

&lt;p&gt;Docker Compose is a tool by Docker that helps to build multiple components at the same time. Really helpful if you're running a project with multiple moving parts, like a database.&lt;/p&gt;

&lt;p&gt;In this case, &lt;code&gt;web&lt;/code&gt; is the Laravel project and &lt;code&gt;db&lt;/code&gt; is the database. The &lt;code&gt;web&lt;/code&gt; container is created from the base image &lt;code&gt;bitnami/laravel&lt;/code&gt;, which is a handy image which has Laravel preinstalled. It adds the &lt;code&gt;app&lt;/code&gt; folder as a "volume" to the container so it can run it. The file gives the container the database credentials so it can connect to it, and it also exposes port &lt;code&gt;8080&lt;/code&gt; so you can open the site with your browser!&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;db&lt;/code&gt; container is a simple container with MySQL installed. The file gives it the password for the &lt;code&gt;root&lt;/code&gt; user and also a name for a database so it can create it.&lt;/p&gt;

&lt;p&gt;That's it!&lt;/p&gt;

&lt;h2&gt;
  
  
   Step 3: Run the containers
&lt;/h2&gt;

&lt;p&gt;Now that we have our &lt;code&gt;docker-compose.yml&lt;/code&gt; file in place, we can give Docker the go-ahead to create both containers with a simple command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Check your site
&lt;/h2&gt;

&lt;p&gt;Give it a few seconds, and your site should be up and running. You should see the following line in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INFO  Server running on [http://0.0.0.0:8000].
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To open it, open &lt;a href="http://localhost:8000" rel="noopener noreferrer"&gt;http://localhost:8000&lt;/a&gt; in your browser.&lt;/p&gt;

&lt;p&gt;Success!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jina31bezlknrepmq4s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jina31bezlknrepmq4s.png" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enjoy your new Laravel site!&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>web</category>
      <category>docker</category>
    </item>
    <item>
      <title>Run WordPress locally using Docker!</title>
      <dc:creator>Savvas Stephanides</dc:creator>
      <pubDate>Tue, 10 Sep 2024 10:47:30 +0000</pubDate>
      <link>https://forem.com/savvasstephnds/run-wordpress-locally-using-docker-5bk2</link>
      <guid>https://forem.com/savvasstephnds/run-wordpress-locally-using-docker-5bk2</guid>
      <description>&lt;p&gt;There are tons of steps to installing WordPress on your local system. You need to install PHP, MySQL, a server, and more. Thankfully there's a much MUCH easier way to install WordPress locally, all thanks to &lt;a href="https://savvas.me/explained/docker" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;! Here's how!&lt;/p&gt;

&lt;h1&gt;
  
  
  Steps
&lt;/h1&gt;

&lt;p&gt;⚠️ Before proceeding, make sure you have &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;Docker installed&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create a new directory
&lt;/h2&gt;

&lt;p&gt;Firstly, we'll need to create a new folder/directory for your project. Create it anywhere you wish and open it / point to it from your Terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-wordpress-blog
&lt;span class="nb"&gt;cd &lt;/span&gt;my-wordpress-blog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Open code editor
&lt;/h2&gt;

&lt;p&gt;Next we're going to create a few files and folders. The easiest way is to open your favourite code editor. Mine is Visual Studio Code which can be opened like this from the Terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;code &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Create a Dockerfile
&lt;/h2&gt;

&lt;p&gt;Use your code editor to create your first file called &lt;code&gt;Dockerfile&lt;/code&gt;. Inside the file, paste these lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM php:7.4-apache

RUN docker-php-ext-install mysqli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what does this do?&lt;/p&gt;

&lt;p&gt;Well, a &lt;code&gt;Dockerfile&lt;/code&gt; is basically a file which gives instructions on how to create an "image" (basically a blueprint) which will be used to create a container, in this case, the container which will house our WordPress site.&lt;/p&gt;

&lt;p&gt;What this specific Dockerfile does is basically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use an Apache and PHP image as a base. This means that our container will have Apache server and PHP already installed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Installs the PHP extension &lt;code&gt;mysqli&lt;/code&gt;. This is an extension that’s needed by WordPress to connect to your MySQL database.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 4: Create a Docker Compose file
&lt;/h2&gt;

&lt;p&gt;Next, we’re going to create a new file called &lt;code&gt;docker-compose.yml&lt;/code&gt;. Paste the following content in this file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./wordpress:/var/www/html&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8080:80"&lt;/span&gt;

  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-db&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;password1&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, what does this do?&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;docker-compose&lt;/code&gt; file is a file which gives instructions to Docker on how to create and run multiple containers at once.&lt;/p&gt;

&lt;p&gt;In our case, our file will create and run 2 containers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A “web” container: This will be where our WordPress site lives. It will create a container based on the &lt;code&gt;Dockerfile&lt;/code&gt; we created earlier. It will also copy the contents of our site, which we’ll download in the next step.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A MySQL server. This is where our data will live. If you’d rather use MariaDB, replace &lt;code&gt;image: mysql&lt;/code&gt; with &lt;code&gt;image: mariadb&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 5: Download WordPress
&lt;/h2&gt;

&lt;p&gt;Now that we have the blueprint for our full stack, it’s time to add some content. We’re going to head to the official &lt;a href="https://wordpress.org/download/" rel="noopener noreferrer"&gt;WordPress site and download the WordPress files&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The download should take a few seconds and it will download a ZIP file.&lt;/p&gt;

&lt;p&gt;The zip file should contain a single folder called “wordpress”. Go ahead and extract it on your drive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Move Wordpress directory to your project
&lt;/h2&gt;

&lt;p&gt;After you've extracted the WordPress folder from the ZIP file, go ahead and move that folder to your project.&lt;/p&gt;

&lt;p&gt;After doing that, this is how the files at the root of your project should look like:&lt;/p&gt;

&lt;p&gt;📁 wordpress&lt;br&gt;
📜 docker-compose.yml&lt;br&gt;
📜 Dockerfile&lt;/p&gt;

&lt;p&gt;In case the WordPress folder isn't called "wordpress", you can go ahead and rename it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 7: Build containers
&lt;/h2&gt;

&lt;p&gt;Now we have everything in place and we can run our site. Firstly though, we need to build the image for the "web" container from the &lt;code&gt;Dockerfile&lt;/code&gt;. To do this, run the &lt;code&gt;build&lt;/code&gt; command from Docker Compose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should take a few seconds to complete and should look like this in your Terminal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fki6c1hlwh7t9frjtzlvt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fki6c1hlwh7t9frjtzlvt.png" width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Run containers
&lt;/h2&gt;

&lt;p&gt;Once the build is completed successfully, you can now run the website. For this, we're using the &lt;code&gt;up&lt;/code&gt; command from Docker Compose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your terminal should look something like this, when running:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnjrbolwodky9jinybzf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnjrbolwodky9jinybzf.png" width="643" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So what just happened? Let's go into some technical detail:&lt;/p&gt;

&lt;p&gt;What we have just done is run two containers: one called "web" for our WordPress website and one called "db", which contains our MySQL database. Then we used commands from Docker Compose to conveniently run both containers at the same time.&lt;/p&gt;

&lt;p&gt;Because these two containers run under the same Compose file, they run under the same "network". This means that they are connected to each other. So, for example, when you need to connect to the database from the web container, the URL to do so is &lt;code&gt;http://db:3306&lt;/code&gt; (because the name of the database container is &lt;code&gt;db&lt;/code&gt;). We'll need this when setting up our site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 9: Setup your website
&lt;/h2&gt;

&lt;p&gt;After a few seconds your site should be up and running. You can access it by opening this URL in your browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once opened, you should see this screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnp5e5aajdk00nu8s3jjy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnp5e5aajdk00nu8s3jjy.png" width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select a language and click Continue.&lt;/p&gt;

&lt;p&gt;You'll be asked for the database credentials. Add these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Database name&lt;/strong&gt;: wordpress&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Username&lt;/strong&gt;: root&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Password&lt;/strong&gt;: password1&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database host&lt;/strong&gt;: db&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After adding these, you can go ahead and run the installation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgi6qocffalidrd958w64.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgi6qocffalidrd958w64.png" alt="Image description" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now add your site details. Here you'll be asked about your site details, like the site name, a username, password etc. Add whatever you like here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jnvvzfjqwg6qp4p3tgj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jnvvzfjqwg6qp4p3tgj.png" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click Install Wordpress.&lt;/p&gt;

&lt;p&gt;After that's done, you're pretty much good to go! 🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcyj5hbq23syxvvwetkx8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcyj5hbq23syxvvwetkx8.png" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click Log In. You'll be presented with a log in screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz6ygg4b9saku2gibvpzu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz6ygg4b9saku2gibvpzu.png" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add the credentials you specified during the set up.&lt;/p&gt;

&lt;p&gt;Tada! That's it! 🎊&lt;/p&gt;

&lt;p&gt;Once you log in, you'll be shown the dashboard:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F54b5qf7tcyak6hn9kwbg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F54b5qf7tcyak6hn9kwbg.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's where you can write articles, create new pages, customise your website to your liking and many many more. This is what makes WordPress so great!&lt;/p&gt;

&lt;p&gt;Click on your site's name on the top right to go to the actual site:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fil1b8m6o13xhtr7s24g2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fil1b8m6o13xhtr7s24g2.png" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is your website up and running locally complete with a handy Dashboard which can be accessed here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:8080/wp-admin/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Success!&lt;/p&gt;

&lt;p&gt;Enjoy editing your new WordPress blog!&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>docker</category>
      <category>php</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What’s your earliest memory of coding?</title>
      <dc:creator>Savvas Stephanides</dc:creator>
      <pubDate>Mon, 29 Jan 2024 09:43:59 +0000</pubDate>
      <link>https://forem.com/savvasstephnds/whats-your-earliest-memory-of-coding-1c7i</link>
      <guid>https://forem.com/savvasstephnds/whats-your-earliest-memory-of-coding-1c7i</guid>
      <description>&lt;p&gt;We had some brilliant discussions on X and Threads and brought back some nice memories.&lt;/p&gt;

&lt;p&gt;So I'm interested to know: what's your earliest memory of coding?&lt;/p&gt;

&lt;p&gt;Let's share some memories!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/SavvasStephnds/status/1750629258131648780" rel="noopener noreferrer"&gt;Discussion on Twitter/X&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.threads.net/@savvascodes/post/C2ib8T_tds_" rel="noopener noreferrer"&gt;Discussion on Threas&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>discuss</category>
    </item>
    <item>
      <title>New computer? Install THIS first... 💻</title>
      <dc:creator>Savvas Stephanides</dc:creator>
      <pubDate>Thu, 23 Nov 2023 14:47:00 +0000</pubDate>
      <link>https://forem.com/savvasstephnds/new-computer-install-this-first-1mak</link>
      <guid>https://forem.com/savvasstephnds/new-computer-install-this-first-1mak</guid>
      <description>&lt;p&gt;So! You just got a new laptop! It's right there sitting on your desk.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzub3sslvm892ba9whw77.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzub3sslvm892ba9whw77.png" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You excitedly switch it on and the logo of the computer's operating system shows up. A few seconds later, you can finally see the desktop.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzic9hve0xdin7dou3lil.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzic9hve0xdin7dou3lil.png" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A shiny new desktop with 2-3 icons. Nothing else. It's time to turn this laptop into a powerful developer machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fuw7d323vkepjodcd9o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fuw7d323vkepjodcd9o.png" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So... let's install some developer tools for our laptop. What's the thing to install first? Surely you'll want to install a programming language, like Python or NodeJS! Or a database, like MySQL or Mongo!&lt;/p&gt;

&lt;p&gt;Nop! You don't need to install any of these things. &lt;strong&gt;Just install Docker&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8901kt948znsl97jbsii.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8901kt948znsl97jbsii.png" width="300" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Docker is a tool that lets you install any of these things on little "containers". Think of them like little computers that live in your computer, with their own operating system, package manager etc.&lt;/p&gt;

&lt;p&gt;For example, do you need to install the latest version of Python? Just enter this command into your Terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull python:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This basically installs the instructions Docker needs to create a new "box" or "container" with its own operating system (Debian in this case) and Python installed. Such instructions are called an &lt;em&gt;image&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Now to work with Python, all you need to do is create a new container using the &lt;code&gt;python&lt;/code&gt; image you installed: Use this command to do so:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -it python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And just like that, you can work in Python! No Python installation required!&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; python

Python 3.12.0 &lt;span class="o"&gt;(&lt;/span&gt;main, Nov 21 2023, 17:38:35&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;GCC 12.2.0] on linux
Type &lt;span class="s2"&gt;"help"&lt;/span&gt;, &lt;span class="s2"&gt;"copyright"&lt;/span&gt;, &lt;span class="s2"&gt;"credits"&lt;/span&gt; or &lt;span class="s2"&gt;"license"&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;more information.

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; print&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
Hello world!
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can do the same for NodeJS!&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; node 
Welcome to Node.js v21.2.0.
Type &lt;span class="s2"&gt;".help"&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;more information.
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; console.log&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
Hello world!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or even MySQL:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my-secret-pw &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 3306:3306 mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  There's more!
&lt;/h2&gt;

&lt;p&gt;You can do all sorts of stuff you can do with Docker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a separate environment with several services working together, using &lt;a href="https://docs.docker.com/compose/" rel="noopener noreferrer"&gt;Docker Compose&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose a specific version of a tool. For example if you need Python 3.7, just use &lt;code&gt;docker pull python:3.7&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And many many more things that will make your workflow so much easier! It definitely improved mine 1000%. I know it will improve yours too.&lt;/p&gt;
&lt;h2&gt;
  
  
  Learn more about Docker
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Learn from a Docker Captain!
&lt;/h3&gt;

&lt;p&gt;Ready to learn more about Docker? Docker Captain Francesco Ciulla (&lt;a class="mentioned-user" href="https://dev.to/francescoxx"&gt;@francescoxx&lt;/a&gt;) will take you through everything you need to know about Docker in 57 minutes!&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;a href="https://www.youtube.com/watch?si=EYHHojVchpX3Ldsv&amp;amp;v=i9M2YBSKp4M&amp;amp;feature=youtu.be" rel="noopener noreferrer"&gt;
      youtube.com
    &lt;/a&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  Docker Docs
&lt;/h3&gt;

&lt;p&gt;Learn more about Docker with the &lt;a href="https://docs.docker.com/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Explore the images available in Docker Hub
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/" rel="noopener noreferrer"&gt;Docker Hub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>beginners</category>
      <category>programming</category>
      <category>development</category>
    </item>
    <item>
      <title>Learning a new tool for your complex project? THIS is the best way to master it! 👍🎓</title>
      <dc:creator>Savvas Stephanides</dc:creator>
      <pubDate>Tue, 14 Nov 2023 17:40:59 +0000</pubDate>
      <link>https://forem.com/savvasstephnds/learning-a-new-tool-for-your-complex-project-this-is-the-best-way-to-master-it-287d</link>
      <guid>https://forem.com/savvasstephnds/learning-a-new-tool-for-your-complex-project-this-is-the-best-way-to-master-it-287d</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0heva19049azvsr4m4t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0heva19049azvsr4m4t.png" alt="Image description" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Software developers learn new stuff all the time. And we all know that the best way to learn new things is by creating projects with that thing. But what if you're building a large project and you've just learned a new library to include in it? Do you just include it in your project straight away? &lt;/p&gt;

&lt;p&gt;NO! Here's what you should do instead!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftfi4nov2d2032ge0y96z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftfi4nov2d2032ge0y96z.png" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Imagine you're working on a to-do app. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6v5e94yjraui6p4h1i5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6v5e94yjraui6p4h1i5.png" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You've been working on this app for months now, so it has become quite complex. &lt;/p&gt;

&lt;p&gt;Now you need a simpler way to update records in the database, so you discover a new Javascript library on NPM, called &lt;code&gt;sqlButEasier&lt;/code&gt;. Perfect for your needs which gets you excited!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3yqce7kjhzkg0zhn5v2e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3yqce7kjhzkg0zhn5v2e.png" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next thing you do, is read the docs from &lt;code&gt;sqlButEasier&lt;/code&gt;. You get a general idea of how it works, and now you want to add it to your big app. &lt;/p&gt;

&lt;p&gt;But you need to practice first, and the big complex app of yours isn't exactly the best place to get your hands dirty. So what do you do?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwv7qt4lxg9wd5c54pevk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwv7qt4lxg9wd5c54pevk.png" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;The solution to this problem is to &lt;strong&gt;create a brand new project and practice there&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjppsrot6b5iz27922rj7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjppsrot6b5iz27922rj7.png" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's right! No better place to practice something new than a &lt;em&gt;new fresh project&lt;/em&gt;, away from the distractions and complexities of an already existing project! Especially if it has hundreds or &lt;em&gt;thousands&lt;/em&gt; of lines of code. &lt;/p&gt;

&lt;p&gt;Just create a new project with the &lt;em&gt;same programming language&lt;/em&gt; and a &lt;em&gt;similar architecture&lt;/em&gt; as your current project, and &lt;strong&gt;test away&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;This way, you'll get some good experience of the tool and once you do, you'll be a &lt;strong&gt;lot&lt;/strong&gt; more confident about using &lt;code&gt;sqlButEasier&lt;/code&gt;. With the new confidence, you can now add the new tool in your large and complex project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3am7x63vy2w5e1fq6dx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3am7x63vy2w5e1fq6dx.png" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try it out next time you need a new library in a large project. Thanks for reading! 👋&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>The complete journey of an open source contribution</title>
      <dc:creator>Savvas Stephanides</dc:creator>
      <pubDate>Mon, 09 Oct 2023 13:00:00 +0000</pubDate>
      <link>https://forem.com/savvasstephnds/the-journey-of-an-open-source-contribution-2dj4</link>
      <guid>https://forem.com/savvasstephnds/the-journey-of-an-open-source-contribution-2dj4</guid>
      <description>&lt;p&gt;"Open source". Two words that when put together bring joy to a developer's heart. In fact, any tool or library you've used, is most likely open source. Which means that the entire code is freely available for anyone to view, download or even make a contribution to.&lt;/p&gt;

&lt;p&gt;But what happens if you want to make your own contribution to a project you use and love? Maybe you want to fix a bug? Or add a new feature? Where does it all start and where does it end?&lt;/p&gt;

&lt;p&gt;This article will describe the journey of an open source contribution, from issue to merge.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzukp7ib68qzn8vrub1ju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzukp7ib68qzn8vrub1ju.png" width="660" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🗣️ &lt;em&gt;This article is brought to you by &lt;a href="https://just-say-something.vercel.app/" rel="noopener noreferrer"&gt;Say Something&lt;/a&gt;. The project which helps you make your first open source contribution by making a very simple change. Check it out!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Station 1: The issue
&lt;/h2&gt;

&lt;p&gt;Our journey starts here. On a website called Github. If a project is open source, chances are the code will live in this website, on its own page. &lt;a href="https://github.com/SavvasStephanides/say-something" rel="noopener noreferrer"&gt;Here's an example&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm116bx30unymyk76222v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm116bx30unymyk76222v.png" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you notice on the page, there's a tab called &lt;em&gt;Issues&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F37xyvaxsze3ddkfq3yx0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F37xyvaxsze3ddkfq3yx0.png" width="700" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is where the bugs that need fixing, the typos that need correcting and the features that need building are located.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d5d424jvlemssgq7qtz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d5d424jvlemssgq7qtz.png" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See an issue that you can work on? Great! On to the next step!&lt;/p&gt;

&lt;h2&gt;
  
  
  Station 2: The assignment
&lt;/h2&gt;

&lt;p&gt;Before you can start working on an issue, the code maintainers have to put a label on the issue that &lt;em&gt;you&lt;/em&gt; are going to work on it, so nobody else does. To do that, you'll have to reply to the issue saying something like "can I work on this issue?".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuieaso5be5aiwkk09swf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuieaso5be5aiwkk09swf.png" width="800" height="615"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The maintainers would be more than happy to assign it to you, if they haven't already assigned it to someone else.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3mgisyjl8nl0955y0wtl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3mgisyjl8nl0955y0wtl.png" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you can work on the issue!&lt;/p&gt;

&lt;h2&gt;
  
  
  Station 3: The fork
&lt;/h2&gt;

&lt;p&gt;You now have the green light to work on the issue. But, you can't just work on the code on someone's else's account. You need to make a copy of it to your own account to start working. This is new copy is called a &lt;em&gt;fork&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To do this, go to the repository page and click on the Fork icon on the top right.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh9tc2oqvtt48nb2tngoj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh9tc2oqvtt48nb2tngoj.png" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll go to a page called &lt;em&gt;Create a new fork&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3gt8uy9cj4b4b2iek6q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz3gt8uy9cj4b4b2iek6q.png" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You don't need to change anything. Just click on &lt;em&gt;Create fork&lt;/em&gt;. After a few seconds, you'll have a copy of the whole code base of the project in your own account!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuoiu1xjm6hrn263erg1k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuoiu1xjm6hrn263erg1k.png" alt="Image description" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's get to work!&lt;/p&gt;

&lt;h2&gt;
  
  
  Station 4: The clone
&lt;/h2&gt;

&lt;p&gt;Now that you've copied the code to your account, it's time to download it to your computer, so you can work on it. The version of the code that will be on your computer is called a &lt;em&gt;clone&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To clone the project, go to your copy of the code (your fork) and click the green Code button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fljnyghqc1nn6zbrlcypg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fljnyghqc1nn6zbrlcypg.png" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the drop down menu, click the "copy" button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwwt904ddx6fayteeafsl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwwt904ddx6fayteeafsl.png" width="539" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The address of your repo will be copied to the clipboard.&lt;/p&gt;

&lt;p&gt;Now head to your Terminal / or command prompt.&lt;/p&gt;

&lt;p&gt;Before you proceed, you'll need to &lt;a href="https://git-scm.com/downloads" rel="noopener noreferrer"&gt;download Git&lt;/a&gt;. Once you do go to the terminal (or command prompt), go to the directory you want to copy the code and enter this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone &amp;lt;the address you copied&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/techforhumans/say-something.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once that's done, go to the directory of your code by using the &lt;code&gt;cd&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd &amp;lt;project name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd say-something
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's make the changes!&lt;/p&gt;

&lt;h2&gt;
  
  
  Station 5: The code
&lt;/h2&gt;

&lt;p&gt;Now you have the code in your computer and you're ready to open it and make changes using your favourite editor.&lt;/p&gt;

&lt;p&gt;💡 If you don't have an editor yet, &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code is a good one to download&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjed3x59kduh52o3jaht3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjed3x59kduh52o3jaht3.png" width="800" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Navigate the code a bit to get familiarised with it and once you do, find the part of the code that has the issue, or where to add the new feature, or fix that typo.&lt;/p&gt;

&lt;p&gt;💡 Some repositories have very specific contribution guidelines, with regards to how the code looks and what must be included in your contribution. Check the repository's &lt;code&gt;README&lt;/code&gt; file or &lt;code&gt;CONTRIBUTING&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Station 6: The push
&lt;/h2&gt;

&lt;p&gt;Once you're done with the changes and you're sure that your new code works, it's time to update your code on Github. We're doing this in 4 steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check&lt;/li&gt;
&lt;li&gt;Add&lt;/li&gt;
&lt;li&gt;Commit&lt;/li&gt;
&lt;li&gt;Push&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Firstly, check your changed files. To do this, run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will list all the files you've changed, created or deleted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdm75a5bca222nl7whh90.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdm75a5bca222nl7whh90.png" width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we're going to "add" those changes. Basically it's a way of saying "I want these files to be pushed to my code on Github. This is the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add -A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command basically says "I want all my changes to be pushed". Next we're going to "commit":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit -m "Added a dad joke"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...which basically means, keep the files I "added" safe until I push them.&lt;/p&gt;

&lt;p&gt;And finally, you're going to push the changes. Simply do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point you'll probably be asked to log in with your Github credentials (depending on the operating system) so they know it's you trying to push changes.&lt;/p&gt;

&lt;p&gt;After that, if you go to your Github repository, your changes should show up there!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsr8er7hzbxoj2xu6d1d1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsr8er7hzbxoj2xu6d1d1.png" width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now there's one more thing to do, and that's adding your changes to the &lt;em&gt;actual&lt;/em&gt; code repository (ie. not your copy of it). &lt;/p&gt;

&lt;h2&gt;
  
  
  Station 7: The pull request
&lt;/h2&gt;

&lt;p&gt;In order for your changes to end up on the actual code for the project, you'll have to show your changes to the code maintainers and ask them nicely for the changes to be included. We do this, with what we call a &lt;em&gt;pull request&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;To start, go to your fork of the code on Github and open the Pull requests tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flseyquieqq4u3nat4k2r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flseyquieqq4u3nat4k2r.png" width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the green &lt;em&gt;New pull request&lt;/em&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flb9ybwr7p6a11dg26zih.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flb9ybwr7p6a11dg26zih.png" width="772" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check your changes one last time and click the green &lt;em&gt;Create pull request&lt;/em&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fupf9vh9dblxnltk367cn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fupf9vh9dblxnltk367cn.png" width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the &lt;em&gt;Open a pull request&lt;/em&gt; page, add a short message (if one isn't present already) and click the &lt;em&gt;Create pull request&lt;/em&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4g9f85txlqzkkkqbpgki.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4g9f85txlqzkkkqbpgki.png" width="800" height="575"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your pull request is ready!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdl13aoqkufg8wc9nvmrs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdl13aoqkufg8wc9nvmrs.png" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now what? Now... we wait... One of the code maintainers will check your pull request and approve it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Last stop: The merge
&lt;/h2&gt;

&lt;p&gt;If you come back to your pull request, and if a code maintainer is happy with your changes, you'll see this message&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;name&lt;/em&gt; approved these changes&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fejixhvtg4s1krtd1hscz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fejixhvtg4s1krtd1hscz.png" width="490" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, what's left is to merge your changes by clicking the green &lt;em&gt;Merge pull request&lt;/em&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1mucl3c4onoj53uxqtuy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1mucl3c4onoj53uxqtuy.png" width="490" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it! 🎉&lt;/p&gt;

&lt;p&gt;You have successfully made a contribution to the project! Your changes are proudly added to the main code of the whole project for the world to enjoy! Congrats!&lt;/p&gt;

&lt;p&gt;If you're still reading up to this point, thank you! How did you find the article? Let me know below!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Check out my project &lt;a href="https://just-say-something.vercel.app/" rel="noopener noreferrer"&gt;Say Something&lt;/a&gt; to practice what you've just learned by making a very simple first contribution. See you there!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>opensource</category>
      <category>github</category>
      <category>beginners</category>
    </item>
    <item>
      <title>5 common terms used in Open Source, explained.</title>
      <dc:creator>Savvas Stephanides</dc:creator>
      <pubDate>Wed, 04 Oct 2023 11:39:38 +0000</pubDate>
      <link>https://forem.com/savvasstephnds/5-common-terms-used-in-open-source-explained-2kp7</link>
      <guid>https://forem.com/savvasstephnds/5-common-terms-used-in-open-source-explained-2kp7</guid>
      <description>&lt;p&gt;October is here which means one thing: &lt;em&gt;Hacktoberfest is back!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;People only are showing their excitement about making their contributions to their favourite open source projects!&lt;/p&gt;

&lt;p&gt;If &lt;em&gt;you&lt;/em&gt; want to start with Open Source, you first need to learn the terms Open Source contributors use.&lt;/p&gt;

&lt;p&gt;In this article, I'll list 5 of the most common terms, and as a bonus, I'll tell you the easiest way to make your very first contribution!&lt;/p&gt;

&lt;h2&gt;
  
  
  5 open source terms
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Open source
&lt;/h3&gt;

&lt;p&gt;What does it mean when a project is &lt;em&gt;open source&lt;/em&gt;? A lot of times the applications and web apps you use have their code (or "source") protected by their companies. Only the developers directly working on the application can see and make changes to the code.&lt;/p&gt;

&lt;p&gt;"Open source" is a complete shift from this. When a project is &lt;em&gt;open source&lt;/em&gt;, it just means that the code is publicly available to everyone to look and make changes to. For example, &lt;a href="https://cdimage.ubuntu.com/releases/20.04/release/source/" rel="noopener noreferrer"&gt;here's the source code for Ubuntu&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Git
&lt;/h3&gt;

&lt;p&gt;Git is a tool that helps you manage your code better. It gives you a history of all the changes you've ever made and makes it easier to update your code. &lt;/p&gt;

&lt;p&gt;Git also makes it easy for a lot of people to work on the same code. This is why a lot of people use it for open source projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Repository
&lt;/h3&gt;

&lt;p&gt;For everyone to browse, make changes and test the code for an open source project, it needs to live somewhere. This &lt;em&gt;somewhere&lt;/em&gt; is what we call a "repository". All the code for a project together with all past and future changes live there.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6w9aylehjjzyojv3prw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6w9aylehjjzyojv3prw.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Fork
&lt;/h3&gt;

&lt;p&gt;A fork is a copy of someone's code that gets added &lt;em&gt;in your own Github account&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;If you need to make changes to a project that &lt;em&gt;you don't own&lt;/em&gt;, the first thing to do is to create a "fork", so that a repository gets created with all the code, &lt;em&gt;which is yours&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Then&lt;/em&gt;, you can make changes if you need to. &lt;/p&gt;

&lt;p&gt;After you've made your changes in your own fork, it's time to ask nicely for your code changes to be added to the original repository!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7fdtunt7r78jas685t5y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7fdtunt7r78jas685t5y.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Pull request
&lt;/h3&gt;

&lt;p&gt;This is where you ask for the changes you've made to be added from the fork (your copy of the code) to the actual code of the project.&lt;/p&gt;

&lt;p&gt;Someone will look at the changes and if they agree with them, the pull request will be approved and your changes will added!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92s8937hd4aly1924wo0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92s8937hd4aly1924wo0.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope this helped you make sense of some common terms. Are there any terms I've missed? Let me know!&lt;/p&gt;

&lt;h2&gt;
  
  
  Make your very first open source contribution!
&lt;/h2&gt;

&lt;p&gt;Now that you've understood the most common terms in open source, it's time to make your first contribution. The best thing you can do in this case, is &lt;strong&gt;start simple&lt;/strong&gt;, instead of jumping straight into huge codebases.&lt;/p&gt;

&lt;p&gt;What if your first contribution was &lt;strong&gt;literally creating a simple file&lt;/strong&gt;, just so you can practice and dip your toes in the water?&lt;/p&gt;

&lt;p&gt;My project &lt;a href="https://just-say-something.vercel.app/" rel="noopener noreferrer"&gt;&lt;em&gt;Say Something&lt;/em&gt;&lt;/a&gt; is here to help! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frzhzsidbtnxk2cs1toyb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frzhzsidbtnxk2cs1toyb.png" width="800" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Say Something is a project where you can share a message with the world. But to do that, you'll need to contribute to the source code by creating a very simple file. Say Something will give you clear instructions on how to post a message in the &lt;em&gt;Write&lt;/em&gt; page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Perfect for first time contributors!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Give it a go:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://just-say-something.vercel.app/" rel="noopener noreferrer"&gt;https://just-say-something.vercel.app/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>opensource</category>
      <category>github</category>
      <category>git</category>
    </item>
    <item>
      <title>In your own opinion, what makes a tutorial beginner friendly?</title>
      <dc:creator>Savvas Stephanides</dc:creator>
      <pubDate>Fri, 28 Jul 2023 14:58:50 +0000</pubDate>
      <link>https://forem.com/savvasstephnds/in-your-own-opinion-what-makes-a-tutorial-beginner-friendly-mg4</link>
      <guid>https://forem.com/savvasstephnds/in-your-own-opinion-what-makes-a-tutorial-beginner-friendly-mg4</guid>
      <description>&lt;p&gt;&lt;a href="https://twitter.com/SavvasStephnds/status/1684830317360627712?s=20" rel="noopener noreferrer"&gt;I asked this question on Twitter&lt;/a&gt; (sorry, X) and got some amazing responses so far. Thought it'd be appropriate to ask here as well. 🙂&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>beginners</category>
      <category>writing</category>
      <category>programming</category>
    </item>
    <item>
      <title>Quickly add random text to your HTML with this simple trick! 🏃‍♂️💨</title>
      <dc:creator>Savvas Stephanides</dc:creator>
      <pubDate>Thu, 06 Jul 2023 14:00:00 +0000</pubDate>
      <link>https://forem.com/savvasstephnds/quickly-add-random-text-to-your-html-with-this-simple-trick-7ef</link>
      <guid>https://forem.com/savvasstephnds/quickly-add-random-text-to-your-html-with-this-simple-trick-7ef</guid>
      <description>&lt;p&gt;It's 11 o'clock on Saturday night.&lt;/p&gt;

&lt;p&gt;Pubs are packed with people drinking and enjoying their night out.&lt;/p&gt;

&lt;p&gt;But not you. You're inside looking into your wide-screen monitor. You decided instead, to dive into the magical world of HTML! 🌈&lt;/p&gt;

&lt;p&gt;So there you are, with Visual Studio Code open. Your HTML code right in front of you with all its colourful glory thanks to the syntax highlighting by VS Code.&lt;/p&gt;

&lt;p&gt;The HTML looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My page&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But that &lt;code&gt;div&lt;/code&gt; looks empty. And that makes you sad. You need to add some text in there to see how it looks in the browser. "Hello world" is cool and all but you're looking for something more realistic to how the div will be used in real life...&lt;/p&gt;

&lt;p&gt;Then you discover the solution! A piece of text written over 2000 years ago is &lt;em&gt;perfect&lt;/em&gt; for this situation. It's called "lorem ipsum".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwssmlh19rjvbm0gw5w3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwssmlh19rjvbm0gw5w3b.png" width="289" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you can add text to your &lt;code&gt;div&lt;/code&gt;! Thing is, every time you need to add some of this text, you need to go to a website, copy some of the text, and paste it in your editor. Is there a faster way, without having to leave your editor? Yes there is!&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;lorem&lt;/code&gt; shortcut!
&lt;/h2&gt;

&lt;p&gt;Open your HTML page in VSCode, point to the part where you want to add some random text, write this: &lt;code&gt;lorem5&lt;/code&gt; and press Tab&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/842793249" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;What just happened? 5 words have been added to your HTML just like that. Now you can save precious seconds, or minutes even, with this shortcut!&lt;/p&gt;

&lt;p&gt;Now try this: write &lt;code&gt;lorem*5&lt;/code&gt; and press Tab:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/842794608" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;5 paragraphs have been pasted into your text file! 🔥&lt;/p&gt;

&lt;p&gt;Now you never need to leave your editor to add some random text to your HTML page!&lt;/p&gt;

&lt;p&gt;And that's the &lt;code&gt;lorem&lt;/code&gt; shortcut which you can use in VS Code or any other editor that supports emmet! Thanks for reading!&lt;/p&gt;

</description>
      <category>html</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>vscode</category>
    </item>
    <item>
      <title>This is the best app for coding on a phone!</title>
      <dc:creator>Savvas Stephanides</dc:creator>
      <pubDate>Tue, 27 Jun 2023 16:22:03 +0000</pubDate>
      <link>https://forem.com/savvasstephnds/this-is-the-best-app-for-coding-on-a-phone-5430</link>
      <guid>https://forem.com/savvasstephnds/this-is-the-best-app-for-coding-on-a-phone-5430</guid>
      <description>&lt;p&gt;Coding is, without a doubt, one of the most interesting and exciting endeavours one can undertake. You start with learning some basic fundamentals, like if statements, loops and functions and you end up building big applications on the web for thousands of users to enjoy.&lt;/p&gt;

&lt;p&gt;Now here's the thing. Typically, to learn coding, you need a big screen. Why? Because syntax in every programming language takes a lot of space. Each line of code can be quite long because of the nature of coding: giving very specific instructions to a computer.&lt;/p&gt;

&lt;p&gt;So what if I want to practice coding on a phone? A phone has a tiny screen which will make it virtually impossible to write code sufficiently on. A small virtual keyboard usually does things worse. So what can we do?&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Apple Shortcuts
&lt;/h2&gt;

&lt;p&gt;The best way to learn to code on a phone is to throw away the syntax you typically find in Javascript or Python, and instead start using apps that lets you drag-and-drop commands.&lt;/p&gt;

&lt;p&gt;One such app is &lt;a href="https://support.apple.com/en-gb/guide/shortcuts/welcome/ios" rel="noopener noreferrer"&gt;Apple Shortcuts&lt;/a&gt; on iPhone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4xm5nqi6heoayd4lx45a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4xm5nqi6heoayd4lx45a.png" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Shortcuts is a great time-saving app for creating tasks. For example, you can create a task which gets your current location and shares it with a contact of your choice. Or start a new workout from your workout app whenever you arrive at the gym.&lt;/p&gt;

&lt;p&gt;So how does it help me learn to code?&lt;/p&gt;

&lt;p&gt;With Apple Shortcuts you can practice coding fundamentals such as:&lt;/p&gt;

&lt;h3&gt;
  
  
  If statements
&lt;/h3&gt;

&lt;p&gt;You can add if blocks to your task so that it executes something only if a condition is met. For example, if some text in your task is "Hello".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpt2uq1ypkacb855algkb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpt2uq1ypkacb855algkb.png" width="794" height="1081"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Loops
&lt;/h3&gt;

&lt;p&gt;To create a loop in Apple Shortcuts, you can use a "Repeat" block. For example, vibrate the device 5 times.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fraxwwthm05iore5icm2b.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fraxwwthm05iore5icm2b.jpeg" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Arrays
&lt;/h3&gt;

&lt;p&gt;You can use arrays in Apple Shortcuts by creating a "List" block. For example, create a list of cities. Then you can create a "Repeat with each" block to speak each city back to the user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3pqvngq36aw4q2pxhlf1.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3pqvngq36aw4q2pxhlf1.jpeg" width="800" height="1010"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Functions
&lt;/h3&gt;

&lt;p&gt;You can run functions by running shortcuts within other shortcuts. For example, create a shortcut which shows a "Hello world" notification...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepvwzs2le5qckkbv10xc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepvwzs2le5qckkbv10xc.png" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...then create a second shortcut which runs the first shortcut.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhqzsgitu88jbllslfodx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhqzsgitu88jbllslfodx.png" width="800" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;There are loads of stuff you can do with Apple Shortcuts on iPhone which can let you practice coding fundamentals. Sure it's not Javascript or Python, but the fundamentals are always the same, regardless how you use them. Have fun with Apple Shortcuts!&lt;/p&gt;

</description>
      <category>coding</category>
      <category>programming</category>
      <category>beginners</category>
      <category>ios</category>
    </item>
  </channel>
</rss>
