{
"$type": "site.standard.document",
"content": {
"$type": "site.standard.content.markdown",
"text": "import CodeSandbox from '../../components/mdx/CodeSandbox.astro'\nimport Youtube from '../../components/mdx/Youtube.astro'\n\nHave you ever had to work on a project that requires lots of parts that need to be installed separately? And one of those parts refuses to work because maybe the other developer worked on Windows and you are on Linux? Well, what I told you that those problems can be (relatively) easily solved? Let's take a look at what Docker is and how we can use it.\n\n## What is Docker?\n\nDocker is a suite of tools allowing you to run containers on your system.\n\n### But what is a container?\n\naccording to [docker.com](https://docker.com), a container is _a sandboxed process on your machine that is isolated from all other processes on the host machine_; this feature has been available on Linux for some time, but Docker managed to standardize and make it available on other operating systems.\n\n## Why would you use a container?\n\nOne of the reasons Docker is so popular is that it allows people to get started and run projects without necessarily needing to install a whole environment. This usually allows for faster onboarding and testing while also simplifying the deployment of services; by using a container you needn't worry about the exact system-specific settings you might need to handle for (most) of the production applications (a single container can be run on (basically) any operating system).\n\n## Images? Containers?\n\nI have mentioned both containers and images so far, but what's the difference?\n\n- An image is the piece of software that contains all the instructions to run your program; the installed programs, the start command etc...\n\n* A container is what runs an Image; it also handles transmitting environment variables, port forwarding with the host, volumes etc... (more details on those later)\n\n## Docker Cheatsheet\n\nNow that we know (kind of) how Docker works, let's create our first image.\n\n### Installing Docker\n\non most systems, you can install [Docker Desktop](https://docker.com) to have a nice GUI to help you. If you can't or don't want to use that, you can also only install the command line tool by running\n\n```bash\ncurl https://get.docker.com | bash -E\n```\n\nthis should download and install docker on your machine (if this does not work, head on over to the [documentation](https://docs.docker.com/get-started/) for system-specific information).\n\n### Creating an Image\n\nFor the sake of an example, we will be using this example\n\n<CodeSandbox projectType='devbox' projectid='cwmtww' />\n\nIt's a simple application running an HTTP server. **Let's dockerize it!**\n\nTo do so, we need to first create a Dockefile; this is a specific file format that enables us to describe how an Image should be created.\nThe simplest Dockerfile for this example project would be:\n\n```bash\nFROM node:lts\nCOPY package.json .\nCOPY index.js .\nRUN npm install\nCMD [\"node\", \"index.js\"]\n```\n\nlet's look a bit more into this file:\n\n- FROM: this line describes the base of our image. We need to tell Docker what to base our image on. To do so, you can specify the image **name** and a **tag** separated by **:**\n\n* COPY: copies a file or folder from our computer's filesystem to the image's.\n\n* RUN: executes a command when building the image\n\n* CMD: this is the command that gets executed when the image runs.\n\nto build this image we can run:\n\n```bash\ndocker build -t learn-docker .\n```\n\nthe -t option allows us to specify a tag for the image to find it more easily.\n\n### Running an Image\n\nOnce we have an image tagged, we can run it by saying:\n\n```bash\ndocker run learn-docker\n```\n\n### Detached Mode\n\nYou'll notice that our terminal window is stuck on the output from our terminal; that's all well and good, but it'd be nice if we wouldn't have to open a new terminal for each container we want to run: enter **detached mode**.\n\n```bash\ndocker run -d learn-docker\n```\n\nRunning a container in detached mode means putting the process in the background which in turn means we get our terminal back.\n\n### Stopping a container\n\nTo stop a container, we first need to know its id. To get a list of all your running containers, you can run the command:\n\n```bash\ndocker ps\n```\n\nThe first element of each line is the container id. Then you can just run:\n\n```bash\ndocker stop <the_id_of_the_container>\n```\n\nand it will stop your container.\n\n### Ports\n\nyou may have noticed that, at least for now, we are unable to access our api. This is because, to put it simply, Docker is sandboxed in its own network, so we need to explicitly map the container's ports to those of our system's. Let's take the command we had before and add a little option\n\n```bash\ndocker run -p 8000:4000 learn-docker\n```\n\nthis should expose port 3000 of our container on port 8000 of our system. If you visit [localhost:8000](http://127.0.0.1:8000), you should see our hello world message.\n\n### Volumes\n\nnow that we have a basic application running, let's see if we can get a bit more out of it. If you take a look at the code, you'll notice that I'm writing my logs into a file inside a **logs** folder; wouldn't it be neat if we could read that data? This is where volumes come in.\n\nBut before we get started, let's make our life a bit simpler; in our Dockerfile, let's specify the **working directory.** This means that when Docker executes the instruction `COPY index.js .`, **.** will be replaced by the working directory we specified earlier. Our new Dockerfile should look something like this:\n\n```bash\nFROM node:lts\nWORKDIR /app\nCOPY package.json .\nCOPY index.js .\nRUN npm install\nCMD [\"node\", \"index.js\"]\n```\n\nOur logs should be stored in `/app/logs`, right? If so, we could define that folder as a **volume**; a volume is a path that is designated as **persistent**, meaning if the container stops the data inside the volume will not be lost. As an additional bonus, a volume can also mirror files and folders in the container to the host's disk. You could, let's say setup a development environment with hot reloading with Dockefiles and maybe a Docker-Compose (maybe a topic for another article).\nlet's revise our execution line a bit:\n\n```bash\ndocker run -p 8000:4000 -v ./logs:/app/logs learn-docker\n```\n\nthis new addition will tell Docker to use (or create) the folder logs in our terminal's current directory as the volume for the path **/app/logs** of our container. This means that if we look inside our logs folder, we should see a file called **log.txt.** If now we send a request to [http://localhost:8000](http://127.0.0.1:8000), we should a new line get appended to that file.\n\nThis is especially useful for databases because you most likely do not want to lose all your customer's data every time you update/stop/restart a container.\n\n## This is the end...\n\nThis has hopefully been a useful introduction to Docker. If you want to learn more about this technology, the first step would be to visit [the official documentation](https://docs.docker.com); it is pretty well written.\nOther useful resources may be:\n\n- Learn Docker in 7 Easy Steps - Full Beginner's Tutorial - Fireship\n\n<Youtube id='gAkwW2tuIqE' />\n\n- Docker Tutorial for Beginners - Programming with Mosh\n\n<Youtube id='pTFZFxd4hOI' />",
"version": "1.0"
},
"path": "/articles/taming-the-whale",
"publishedAt": "2023-03-09T00:00:00.000Z",
"site": "at://did:plc:dgtaz4vldacvqhvvmdvoc4ad/site.standard.publication/3mfbydibiwc7f",
"tags": [
"docker",
"programming",
"devops",
"beginners",
"introduction"
],
"textContent": "import CodeSandbox from '../../components/mdx/CodeSandbox.astro'\nimport Youtube from '../../components/mdx/Youtube.astro'\n\nHave you ever had to work on a project that requires lots of parts that need to be installed separately? And one of those parts refuses to work because maybe the other developer worked on Windows and you are on Linux? Well, what I told you that those problems can be (relatively) easily solved? Let's take a look at what Docker is and how we can use it.\n\nWhat is Docker?\n\nDocker is a suite of tools allowing you to run containers on your system.\n\nBut what is a container?\n\naccording to docker.com, a container is a sandboxed process on your machine that is isolated from all other processes on the host machine; this feature has been available on Linux for some time, but Docker managed to standardize and make it available on other operating systems.\n\nWhy would you use a container?\n\nOne of the reasons Docker is so popular is that it allows people to get started and run projects without necessarily needing to install a whole environment. This usually allows for faster onboarding and testing while also simplifying the deployment of services; by using a container you needn't worry about the exact system-specific settings you might need to handle for (most) of the production applications (a single container can be run on (basically) any operating system).\n\nImages? Containers?\n\nI have mentioned both containers and images so far, but what's the difference?\nAn image is the piece of software that contains all the instructions to run your program; the installed programs, the start command etc...\n\n A container is what runs an Image; it also handles transmitting environment variables, port forwarding with the host, volumes etc... (more details on those later)\n\nDocker Cheatsheet\n\nNow that we know (kind of) how Docker works, let's create our first image.\n\nInstalling Docker\n\non most systems, you can install Docker Desktop to have a nice GUI to help you. If you can't or don't want to use that, you can also only install the command line tool by running\n\nthis should download and install docker on your machine (if this does not work, head on over to the documentation for system-specific information).\n\nCreating an Image\n\nFor the sake of an example, we will be using this example\n\nIt's a simple application running an HTTP server. Let's dockerize it!\n\nTo do so, we need to first create a Dockefile; this is a specific file format that enables us to describe how an Image should be created.\nThe simplest Dockerfile for this example project would be:\n\nlet's look a bit more into this file:\nFROM: this line describes the base of our image. We need to tell Docker what to base our image on. To do so, you can specify the image name and a tag separated by :\n\n COPY: copies a file or folder from our computer's filesystem to the image's.\n\n RUN: executes a command when building the image\n\n CMD: this is the command that gets executed when the image runs.\n\nto build this image we can run:\n\nthe -t option allows us to specify a tag for the image to find it more easily.\n\nRunning an Image\n\nOnce we have an image tagged, we can run it by saying:\n\nDetached Mode\n\nYou'll notice that our terminal window is stuck on the output from our terminal; that's all well and good, but it'd be nice if we wouldn't have to open a new terminal for each container we want to run: enter detached mode.\n\nRunning a container in detached mode means putting the process in the background which in turn means we get our terminal back.\n\nStopping a container\n\nTo stop a container, we first need to know its id. To get a list of all your running containers, you can run the command:\n\nThe first element of each line is the container id. Then you can just run:\n\nand it will stop your container.\n\nPorts\n\nyou may have noticed that, at least for now, we are unable to access our api. This is because, to put it simply, Docker is sandboxed in its own network, so we need to explicitly map the container's ports to those of our system's. Let's take the command we had before and add a little option\n\nthis should expose port 3000 of our container on port 8000 of our system. If you visit localhost:8000, you should see our hello world message.\n\nVolumes\n\nnow that we have a basic application running, let's see if we can get a bit more out of it. If you take a look at the code, you'll notice that I'm writing my logs into a file inside a logs folder; wouldn't it be neat if we could read that data? This is where volumes come in.\n\nBut before we get started, let's make our life a bit simpler; in our Dockerfile, let's specify the working directory. This means that when Docker executes the instruction , . will be replaced by the working directory we specified earlier. Our new Dockerfile should look something like this:\n\nOur logs should be stored in , right? If so, we could define that folder as a volume; a volume is a path that is designated as persistent, meaning if the container stops the data inside the volume will not be lost. As an additional bonus, a volume can also mirror files and folders in the container to the host's disk. You could, let's say setup a development environment with hot reloading with Dockefiles and maybe a Docker-Compose (maybe a topic for another article).\nlet's revise our execution line a bit:\n\nthis new addition will tell Docker to use (or create) the folder logs in our terminal's current directory as the volume for the path /app/logs of our container. This means that if we look inside our logs folder, we should see a file called log.txt. If now we send a request to http://localhost:8000, we should a new line get appended to that file.\n\nThis is especially useful for databases because you most likely do not want to lose all your customer's data every time you update/stop/restart a container.\n\nThis is the end...\n\nThis has hopefully been a useful introduction to Docker. If you want to learn more about this technology, the first step would be to visit the official documentation; it is pretty well written.\nOther useful resources may be:\nLearn Docker in 7 Easy Steps - Full Beginner's Tutorial - Fireship\nDocker Tutorial for Beginners - Programming with Mosh",
"title": "Taming the whale: introduction to Docker",
"updatedAt": "2026-05-17T13:09:11.498Z"
}