Docker Crash Course #5 - The Dockerfile

Net Ninja · Beginner ·🌐 Frontend Engineering ·4y ago

Key Takeaways

Explains the Dockerfile and how to use it to create Docker images

Full Transcript

so then in the last lesson we talked briefly about how docker images are made up of different layers right and generally when we're making a new docker image our first layer is going to be some kind of parent image like the node one that we downloaded and then this parent image would normally be an operating system and something like node or python or php or ruby or something else entirely then on top of this initial layer we'd add our own extra layers which add more to the image or change the image so that's how you can think of layers as changes to the image that we're ultimately making for example we'd copy source code over to the image would install dependencies on the image and we'd store other information like commands inside the image as well but how do we do all this how do we actually create our own docker image with all of these different layers well it's pretty simple to do we just create something called a dockerfile which is like a set of instructions to docker to create the image and the dockerfile essentially lists out all of these different layers or instructions to create those layers on an image so now let's take a quick look at how to make a dockerfile and then use it to create a docker image now i've already got open a dummy application here in this api folder which you can find on the lesson 5 branch of the course files on github the link to that is going to be down below the video and this application is just a simple node app which uses express to create a very very very simple api so you can see right here in the app file that we have a simple express application set up and we're listening for requests on port 4000 and we have this handler function right here for this endpoint which is just basically the root endpoints so when a get request comes in to this endpoint then as a response we'll send this json data so like i said a really simple api but don't worry if you don't actually understand this code here it's not overly relevant to what we're about to do with docker it's just a dummy node application that we're going to create a docker image for and then eventually run it inside a container so this application also has dependencies that need to be installed for its work and those dependencies are listed inside the package.json file okay so you can see right here for example we have express as a dependency now normally if i wanted to run this application directly on my computer i'd first of all need to run npm install in this project directory so i'd open up a terminal and type npm install and that would install the project dependencies inside this project folder in a node modules folder and then after that to run the application i just type nodeapp.js which is the name of the file i want to run and that would start the application running directly on my computer and it would be using the node version that i have installed on my computer but we don't want to do that we want to run the application inside an isolated container with its own version of node running inside it so to do that we need to make an image and that image should contain the initial parent image layer to say what version of node and linux distribution we want the container to run and then after that the extra layers which will be to copy this source code and all the dependencies into it and then some extra information too and again the way we make this image is by first making a docker file so let's start now by making that docker file in the root of this project folder so the name of the dockerfile is just dockerfile with a capital d and no extension at the end of it i remember this dockerfile is like a set of instructions which tells docker how to create a specific image with all of its different layers and each instruction is going to be on a different line inside this file and generally speaking each line in a docker file kind of represents a different layer in our final image now before you start actually writing this out it might be a good idea to install the docker package for vs code so if you want to install that go to extensions and then just search for docker up here and it's this package right here so click install and you can read about it right here so install that first of all then we can start to write out this file so the first instruction the first layer of our image is going to be the parent image the node image that we can download from docker hub so this goes at the top of the file because it will be the first layer or the initial layer of the image that we want to create now to do this we simply write from in capital letters and then the name of the image that we want in our case that's going to be node and then a colon and say 17 hyphen alpine so what this line says is that to begin with we want to pull in the node image into our image as the initial layer so when we run this file later to create our image it will pull in the node image first of all and it's going to pull it either from the docker hub repository if we haven't already downloaded it or our own computer if we have now we downloaded a node image but it wasn't exactly this one it was kind of the default version of that image the latest one but this one now has this tag 17 hyphen alpine which means get version 17 of node and use the alpine distribution of linux all right so it's going to download this from docker hub so then that is our initial layer apparent image and to add a parent image like this as the initial layer remember we use the from keyword at the top of our docker file so then on top of this we also need to add our own additional layers now the next layer i want to add is to copy all of our source code into the image so this app.js file and these json files as well and to do that we say copy and capital letters then a dot then a space then a dot again but what does this mean well first of all we say copy which means copy some files to the image and then the first dot is a relative path to the directory i want to copy my source files from and since those source files are in the same kind of root directory as the docker file then the path is just going to be a single dot which means the current directory if all my source code was in a source folder over here then instead of just a dot it would be dot and then forward slash source now the second dot is the path inside the image that i want to copy my source code to remember i said the images have their own folder structure so right now we just say dot which means copy into the root directory of the image that we're creating now a lot of the time we don't copy into the root directory because it might clash with other files or folders inside that root directory so instead we could say copy to a path which is forward slash app for example and then this would copy our source files into a new folder called app inside the image all right so the next layer of the image would be all the dependencies that we need to install on the image now to install dependencies into a project we'd run npm install and we can do a similar thing to the image that we make we're allowed to specify commands that we want to run in the image as the image gets built so at build time and to specify a command we'd use the run instruction now the command that we want to run is npm install which installs all the dependencies listed in the package.json file remember we copied that file over to the image in the previous layer so this run instruction right here tells docker to run a command on the image itself as this layer is being added on while the image is being built and so then all the project dependencies will be installed onto the image as well but there is one slight problem the command is going to be run inside the root directory of the image but our package.json file got copied to an app folder so that means that when this command gets run in the root folder of the image it won't see the package.json file in that folder and therefore it won't install the dependencies so for this to work we need to run this command in the same directory as our package.json file so that's inside the app folder right and the way we do that is by specifying a working directory for the image so the way we do this is by adding a work dir which stands for work directory instruction to the dockerfile and i'm going to place this at the top just underneath the first instruction so that every instruction after this can use that working directory and for a value i'm just going to say forward slash app so what does this working directory do for us well it tells docker that when we run commands on the image in future after this instruction or if we specify paths inside the image to do it from this working directory so now when a command is run like this npm install it will do it from inside the app folder so that is one problem now solved but there is one other change that we need to quickly make now that we have this working directory it's the path that we want to copy to right here because this is now a path relative to that working directory which means that the source code will now get copied into forward slash app and then forward slash up again so to solve this we can just replace this with a single dot and that means copy it to the root directory relative remember to the working directory now and so now everything should work correctly so again we can specify a working directory so that any commands that we run or any paths that we specify after this instruction are done relative to this working directory now there is one more instruction i want to create and that's another command to actually run the application in the container now to run this node application we'd run the command normally node app.js in the terminal right so you might think that we just add another run instruction right here at the bottom to say node app.js but we don't do that let's think about why not when we add a run instruction it runs a command as the image is being built so at build time and remember the image is not a running application it's just a blueprint for a container and the container is the thing that actually runs the application in other words it's a running instance of the image so it makes sense to use the run instruction for installing dependencies at build time onto the image as the image is being created and that way they're all included in the image and ready for when we run the container based on that image but it doesn't make sense to run the node app.js command build time because we're not trying to run the application when we're building the image we're just making the image right and instead we want to run the node app.js command when we have a running instance of the image inside the container so how do we specify this well instead of using the run instruction we use an instruction called cmd and cmd allows us to specify any commands that should be run at runtime when the container begins to run but the way we write this command is a little bit different we write the command as an array of strings in double quotes so the first one would be node and then the second one the second element would be app.js and then when the container runs this command will be run right here which is node app.js and that is going to spin up our application inside the container all right so now there is one more thing i want to add to this docker file and that is an expose instruction which tells docker which port the container should expose because remember inside the app.js file when we start up the server we listen for request on port 4000 now this app is going to be running inside the container so the port is going to be owned by the container as well not our computer but by the container and to make requests to this api we need to send them to the container using this port number so in the dockerfile we can add an instruction which tells docker what port is going to be exposed by the container which in our case is going to be port 4000 now this exposed instruction is kind of optional we only really need it here if we're going to be running images and spinning up containers using the docker desktop application because docker desktop will use this information in the docker file to set up something called port mapping later on and we'll learn about that later as well but if we're running containers from the command line then it's not really needed but i still like to add it so that at a glance at this docker file i can see which port is going to be exposed for this application so i'm going to keep it in and that's pretty much it for the dockerfile so we specify a parent image at the start as the first layer then we specify a working directory of the image then we copy over all the source files then we run the npm install command at build time to add all the dependencies to the image then we say expose port 4000 and then finally we specify a command that should be run only when the container based on this image is run now the final step is to actually build this image and that's really simple to do we just have to run a single docker command in the same directory that this docker file is in so open up a terminal and make sure you're in the project directory down here the api directory if you're not just cd into the api folder then type docker and then we use a command called build so docker build and then after that we can use a flag hyphen t which stands for tag and this allows us to basically give the image a name which i'm going to call my app and then after that we'll put a dot at the end now the dot is a relative path to the docker file from the directory we're in inside this terminal right here and since we're in the same directory as the dockerfile then the path is just a dot to say this current same directory that we're in so now hit enter and then this is going to go through each of the instructions in the docker file and do each one in turn and each time it does one of those it's essentially adding a new layer to the docker image that we're creating right now and you can see each of those steps happening as you watch the build process in the terminal all right so once that's all done the image is created and we don't see any extra file in this project to represent that image anywhere at all it's stored away for us in a special docker folder on our computer but if we open up docker desktop then we can see this extra image now listed right here with the name that we gave it my app awesome

Original Description

Hey gang, in this Docker tutorial we'll talk about the Dockerfile and how we use it to create docker images. 🐱‍💻 Access the course files on GitHub: https://github.com/iamshaunjp/docker-crash-course 🐱‍💻 Node.js Course: On Net Ninja Pro - https://netninja.dev/p/node-js-crash-course On YouTube - https://www.youtube.com/playlist?list=PL4cUxeGkcC9gcy9lrvMJ75z9maRw4byYp 🐱‍💻 Modern JavaScript Course: On Net Ninja Pro - https://netninja.dev/p/modern-javascript-from-novice-to-ninja On Udemy - https://www.thenetninja.co.uk/udemy/modern-javascript On YouTube - https://www.youtube.com/watch?v=iWOYAxlnaww&list=PL4cUxeGkcC9haFPT7J25Q9GRB_ZkFrQAc 🐱‍💻 React Course: On Net Ninja Pro - https://netninja.dev/p/build-websites-with-react-firebase On Udemy - https://www.thenetninja.co.uk/udemy/react-and-firebase 🐱‍💻 VS Code - https://code.visualstudio.com/ 🐱‍💻 Docker Hub - https://hub.docker.com/ 🐱‍💻 Docker docs - https://docs.docker.com/
Watch on YouTube ↗ (saves to browser)
Sign in to unlock AI tutor explanation · ⚡30

Playlist

Uploads from Net Ninja · Net Ninja · 0 of 60

← Previous Next →
1 Regular Expressions (RegEx) Tutorial #14 - Matching a Username
Regular Expressions (RegEx) Tutorial #14 - Matching a Username
Net Ninja
2 Regular Expressions (RegEx) Tutorial #15 - Email RegEx Pattern
Regular Expressions (RegEx) Tutorial #15 - Email RegEx Pattern
Net Ninja
3 Regular Expressions (RegEx) Tutorial #16 - Finishing Touches
Regular Expressions (RegEx) Tutorial #16 - Finishing Touches
Net Ninja
4 GraphQL Tutorial #1 - Introduction to GraphQL
GraphQL Tutorial #1 - Introduction to GraphQL
Net Ninja
5 GraphQL Tutorial #2 - A Birdseye View of GraphQL
GraphQL Tutorial #2 - A Birdseye View of GraphQL
Net Ninja
6 GraphQL Tutorial #3 - Project (stack) Overview
GraphQL Tutorial #3 - Project (stack) Overview
Net Ninja
7 GraphQL Tutorial #4 - Making Queries (front-end preview)
GraphQL Tutorial #4 - Making Queries (front-end preview)
Net Ninja
8 GraphQL Tutorial #5 - Express App Setup
GraphQL Tutorial #5 - Express App Setup
Net Ninja
9 GraphQL Tutorial #6 - Setting up GraphQL
GraphQL Tutorial #6 - Setting up GraphQL
Net Ninja
10 GraphQL Tutorial #7 - GraphQL Schema
GraphQL Tutorial #7 - GraphQL Schema
Net Ninja
11 GraphQL Tutorial #8 - Root Query
GraphQL Tutorial #8 - Root Query
Net Ninja
12 GraphQL Tutorial #9 - The Resolve Function
GraphQL Tutorial #9 - The Resolve Function
Net Ninja
13 GraphQL Tutorial #10 - Testing Queries in Graphiql
GraphQL Tutorial #10 - Testing Queries in Graphiql
Net Ninja
14 GraphQL Tutorial #11 - GraphQL ID Type
GraphQL Tutorial #11 - GraphQL ID Type
Net Ninja
15 GraphQL Tutorial #12 - Author Type
GraphQL Tutorial #12 - Author Type
Net Ninja
16 GraphQL Tutorial #13 - Type Relations
GraphQL Tutorial #13 - Type Relations
Net Ninja
17 GraphQL Tutorial #14 - GraphQL Lists
GraphQL Tutorial #14 - GraphQL Lists
Net Ninja
18 GraphQL Tutorial #15 - More on Root Queries
GraphQL Tutorial #15 - More on Root Queries
Net Ninja
19 GraphQL Tutorial #16 - Connecting to mLab
GraphQL Tutorial #16 - Connecting to mLab
Net Ninja
20 GraphQL Tutorial #17 - Mongoose Models
GraphQL Tutorial #17 - Mongoose Models
Net Ninja
21 GraphQL Tutorial #18 - Mutations
GraphQL Tutorial #18 - Mutations
Net Ninja
22 GraphQL Tutorial #19 - More on Mutations
GraphQL Tutorial #19 - More on Mutations
Net Ninja
23 GraphQL Tutorial #20 - Updating the Resolve Functions
GraphQL Tutorial #20 - Updating the Resolve Functions
Net Ninja
24 GraphQL Tutorial #21 - GraphQL NonNull
GraphQL Tutorial #21 - GraphQL NonNull
Net Ninja
25 GraphQL Tutorial #22 - Adding a Front-end
GraphQL Tutorial #22 - Adding a Front-end
Net Ninja
26 GraphQL Tutorial #23 - Create React App
GraphQL Tutorial #23 - Create React App
Net Ninja
27 GraphQL Tutorial #24 - Book List Component
GraphQL Tutorial #24 - Book List Component
Net Ninja
28 GraphQL Tutorial #25 - Apollo Client Setup
GraphQL Tutorial #25 - Apollo Client Setup
Net Ninja
29 GraphQL Tutorial #26 - Making Queries from React
GraphQL Tutorial #26 - Making Queries from React
Net Ninja
30 GraphQL Tutorial #27 - Rendering Data in a Component
GraphQL Tutorial #27 - Rendering Data in a Component
Net Ninja
31 GraphQL Tutorial #28 - Add Book Component
GraphQL Tutorial #28 - Add Book Component
Net Ninja
32 GraphQL Tutorial #29 - External Query File
GraphQL Tutorial #29 - External Query File
Net Ninja
33 GraphQL Tutorial #30 - Updating Component State
GraphQL Tutorial #30 - Updating Component State
Net Ninja
34 GraphQL Tutorial #31 - Composing Queries
GraphQL Tutorial #31 - Composing Queries
Net Ninja
35 GraphQL Tutorial #32 - query variables
GraphQL Tutorial #32 - query variables
Net Ninja
36 GraphQL Tutorial #33 - Re-fetching Queries
GraphQL Tutorial #33 - Re-fetching Queries
Net Ninja
37 GraphQL Tutorial #34 - Book Details Component
GraphQL Tutorial #34 - Book Details Component
Net Ninja
38 GraphQL Tutorial #36 - Styling the App
GraphQL Tutorial #36 - Styling the App
Net Ninja
39 GraphQL Tutorial #35 - Making a Single Query
GraphQL Tutorial #35 - Making a Single Query
Net Ninja
40 Build Apps with Vue & Firebase - Udemy Course
Build Apps with Vue & Firebase - Udemy Course
Net Ninja
41 Updated Vue & Firebase Course (Udemy)
Updated Vue & Firebase Course (Udemy)
Net Ninja
42 Vue & Firebase Real-time Chat (Preview) #1 - Intro
Vue & Firebase Real-time Chat (Preview) #1 - Intro
Net Ninja
43 Vue & Firebase Real-time Chat (Preview) #2 - Project Structure
Vue & Firebase Real-time Chat (Preview) #2 - Project Structure
Net Ninja
44 Vue & Firebase Real-time Chat (Preview) #3 - Firestore Setup
Vue & Firebase Real-time Chat (Preview) #3 - Firestore Setup
Net Ninja
45 Vue & Firebase Real-time Chat (Preview) #4 - Welcome Screen
Vue & Firebase Real-time Chat (Preview) #4 - Welcome Screen
Net Ninja
46 Vue & Firebase Real-time Chat (Preview) #5 - Props in Routes
Vue & Firebase Real-time Chat (Preview) #5 - Props in Routes
Net Ninja
47 Vue & Firebase Real-time Chat (Preview) #6 - Route Guards
Vue & Firebase Real-time Chat (Preview) #6 - Route Guards
Net Ninja
48 Vue & Firebase Real-time Chat (Preview) #7 - Chat Window
Vue & Firebase Real-time Chat (Preview) #7 - Chat Window
Net Ninja
49 Vue & Firebase Real-time Chat (Preview) #8 - New Message Component
Vue & Firebase Real-time Chat (Preview) #8 - New Message Component
Net Ninja
50 Object Oriented JavaScript Tutorial #1 - Introduction
Object Oriented JavaScript Tutorial #1 - Introduction
Net Ninja
51 Object Oriented JavaScript Tutorial #2 - Object Literals
Object Oriented JavaScript Tutorial #2 - Object Literals
Net Ninja
52 Object Oriented JavaScript Tutorial #3 - Updating Properties
Object Oriented JavaScript Tutorial #3 - Updating Properties
Net Ninja
53 Object Oriented JavaScript Tutorial #4 - Classes
Object Oriented JavaScript Tutorial #4 - Classes
Net Ninja
54 Object Oriented JavaScript Tutorial #5  - Class Constructors
Object Oriented JavaScript Tutorial #5 - Class Constructors
Net Ninja
55 Object Oriented JavaScript Tutorial #6 - Class Methods
Object Oriented JavaScript Tutorial #6 - Class Methods
Net Ninja
56 Object Oriented JavaScript Tutorial #7 - Method Chaining
Object Oriented JavaScript Tutorial #7 - Method Chaining
Net Ninja
57 Object Oriented JavaScript Tutorial #8 - Class Inheritance
Object Oriented JavaScript Tutorial #8 - Class Inheritance
Net Ninja
58 Object Oriented JavaScript Tutorial #9 - Constructors (under the hood)
Object Oriented JavaScript Tutorial #9 - Constructors (under the hood)
Net Ninja
59 Object Oriented JavaScript Tutorial #10 - Prototype
Object Oriented JavaScript Tutorial #10 - Prototype
Net Ninja
60 Object Oriented JavaScript Tutorial #11 - Prototype Inheritance
Object Oriented JavaScript Tutorial #11 - Prototype Inheritance
Net Ninja

Related Reads

📰
I Built a 100% Free, Frictionless Resume Builder with Direct PDF/Word Exports
Learn how to build a free and frictionless resume builder with direct PDF and Word exports, and discover the tools and techniques used to create it
Dev.to · Solangi Waqas
📰
How to Deploy Angular SSR on Cloudflare Workers for Free — No VPS, No Fees, No Credit Card.
Learn to deploy Angular SSR on Cloudflare Workers for free without needing a VPS, fees, or credit card
Medium · JavaScript
📰
How I Added Browser-Based HEIC to JPG Conversion (No Server, No Upload)
Learn how to convert HEIC to JPG in the browser without server upload using heic2any
Dev.to · Rushikesh Lade
📰
Angular Signals in 2026: From Fundamentals to Architect-Level Patterns
Learn Angular Signals fundamentals and architect-level patterns to improve your Angular applications
Dev.to · Amanulla Khan
Up next
Elementor Angie Ai Plugin Tutorial
Quick Tips - Web Desiign & Ai Tools
Watch →