25 E05 - Building GOlang Apps in Docker Container #docker #golang

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello there welcome back to going around and today we're going to combine building go application in our docker container so far what we've been doing is building our application outside of the docker container and we have to be careful to make sure we build a linux binary and a few times you've probably seen me say go build and i'll put a mac binary because on a mac or if you're on windows you then put a windows binary and then have to go back and go oh this doesn't work i have to do go os to set the correct operating system right for the binary and so we can get rid of that headache uh of course if you're in linux then this is not a problem and we can just have our source code be copied into the image and then run the build go build command within the image and we'll get a binary that's correct now there's a couple of advantages um for doing it this way and i'll show you that today what i'm going to show you is using a builder image right now we can you know possibly copy the code in build it and then remove the code but yeah that seems like a little bit hacky right so what if the delete failed now your code is in the container the container is compromised your code is exposed so we'll see how to get around that that's the objective here is using a container to build our code and then copying over the code that we want to run to another container so be using like stage building but again using several containers and you'll see how we'll put this in one docker file all right before we jump into the material please do me a huge favor hit that thumbs up button if you um enjoying the material like what you're seeing hit the subscribe button if you are not already subscribed hit the bell hit the bell notification so that you can be notified when i post videos all right thanks a lot for doing that for me and now let's jump in so here i am on my command line and we'll start off by copying um our previous example so that was part three so i'm gonna do part three and i'm going to copy that as essentially an alcohol building go apps in docker container and so hopefully this is going to be a very short video but we'll see so docker container so there we go all right so as usual i'll bring my visual studio code editor in this directory and let's also trust this workspace whatever that's about and let's also in the bottom here let's do the same thing go to this directory container and there we are okay so like i said we start not exactly we were before now before we were using um this log directory so we can get log from our container so we can see whatever is written inside our container is reflected outside for now i'm going to remove this directory because that's not of the focus of today's video but everything we've done before um still work now if you do not map the directory even though we say export volume remember it just simply use an internal um directory within the container it's just that we wouldn't get to see it all right so we don't really have to do anything to our code so i'm going to leave that as it is now if you remember what we're doing is we say um where is copy oh we add app to our project right so we would have to build it let's just call it app one for now and so we'll have to build it and copy it to our directory and our working directory here is root no we don't have to run our application auto group like we could run it out of some other directory right and maybe there is an argument to say that oh we should not run as rude and i'll give you a link to how you can do even more secure applications i'm not going to focus on that here but just know um we can get rid of some of these because these were sort of play things to show us that we have multiple commands that we can run um but we don't have to keep all of this stuff right um updating it and so on we don't have to do all of that stuff now if we just step back here and say what would we need in order so that when we build this image we can say add file 1 to our root directory so that later on our entry point is you know run this application with this parameter we would need to say go os this is what i'm talking about equals to linux and then go bill and make sure that oh we can build our application um as a point now this of course with this silly long name with the directory name so let's remove that and let's rebuild it i said minus out let's cut it up one right we'll have to make sure that we do that okay but again we don't want to be have to think about doing that so instead we want to possibly do is say what we should do is copy um our source directory or the current directory we have our code right copy all of it into the container and then have it built now if we copy our current directory we're not only going to be copying let's remove app for example not only are we going to be copying um the main that go but we are also copying the docker file we don't really need to do that and for this example it might seems easier to just copy main.go but let's pretend that really what we have is a very complex application that's you know we have like a source directory and within source we have maybe a good.mod file you know it says module let's call it app1 for example and within there we drop our main.go so this would represent the fact that i put this on a directory means that so we could have a ton of files under there and and and that's you know abstract away the details and complexity of our application so in that case we might really want to do is in our docker file here is actually say copy you know or source directory and so where should we copy it well again we'll copy it to our working directory here which is the root directory um so let's do this um we can um not that that that we can say let's come bring this down and say let's do that and so we start off by saying our application exposure just component exposes port 8000 nothing change we make a directory slash data we expose that as a volume and our current working directory is you know you know root let's say we can see that and then copy to the root directory you know um the source directory source um i think if we do source dot it just should also work i think what's gonna happen is the contents of that directory is gonna be copied into root so i still want it to be called probably um yeah let's leave it as it is so that way oh you know what even better um let's make the working directory slash src and so now i'll copy um code to the source to root source and so the contents of my source here so this is going to be go mod all this other stuff is going to appear in this directory but because that's my working directory then i can simply say run a command to build it so we can say run and what i want to do is to be able to run and so i can run it this way so i can do one string like this like go build or i can do it as an array and pass the individual arguments that go is the command itself and these are its argument so i can do build and i can say that i'm the next option is argument is minus o and we want to use app one so something like that so i can totally do that right and then once we have the application there it's in this current directory which is fine we could run it this way or we can also be explicit about where we want to run from you know source data of course we can have our output be written somewhere else if we didn't want to run from our root directory so for now i'll leave that i'm just showing you all the options so let's see um so this is what is this complaint about i don't know why it's completed maybe it's a pro the um editor needs to close and reopen um i've seen issues with that before so for now i think it's fine so i'm going to ignore it and so let's clean up and let's do docker build and so what i want to do is build um the in the current directory tag it as section 25.5 and let's call it up one version one and so let's run and see if this works and so there we go and it's giving me an exception here container that linux that go starting container process close exe go executable file on that phone this is understandable because in this container we did not this is ubuntu we did not install the google executable well thankfully for us and so let me see i should have that here so thankfully for us if you go to dockerhub.com and then you search for golang you'll see that these are official docker official images this is from the go team they've provided a slow crap ton of images if you like for you to be able to do go development and actually tell you and there are a bunch of them some of them are based off of the ubuntu i believe but some of them are based off of alpine which is known for being very very small um you know compact image and people use that tend to tend to use that for um hide it as their base where you do from you know in your docker container and then built on bill on top of that um because it comes basically very little in it it's already stripped and so um they show you here all you can do is you can say from like gold lang and then you know set your work in directory and of course you can do it this way um where you're working directory is called source app and then you copy in your code and then you go to go get and install go get what just get all the dependencies but we're just going to sidestep all that because using go module i don't actually have to do an explicit call get i'll just do from go now why not ubuntu i could use ubuntu to update and then add go language but why do that when to go steam has provided you know the golang image and i'm not i'm not going to specify a version of gold line here i'm going to use the latest so if i go back here clean up and i rerun and now it should be successful and so you can see it's downloading some stuff and it fetched all the stuff that my application needed these are all the dependencies right and so it built my application it says successfully built now now that that's built i should be able to run it right so if i do docker run and then i say run as a daemon minus d i give the name app one and i'm gonna map the local port 8080 to port 8000 because that's where my application is listening to and that is what it's exposes really is the important thing and then it's going to be this um tag that we just built and so if i do that i should give back an image a container id and i can say docker log and i should be able to log and then see that oh yeah my server log the toe is started so so that's that's good and that's fine i could stop doing that but i can do curl and if i do localhost i can see that i get back a message hello from this container you can see that's the container name d so everything is working just as before so i was able to build and have the application there well here's what i want to show you i can say docker image list and let's grab for section whatever that's what the thing was called no i don't want to edit anything um but look at this this is our image that we built and you can see it's 860 megabytes that's a big fat image it's pretty big and so um what you might want to do is be able to reduce the size of that image now let's see how big the golang image itself is so let's do go line and we can see that golang latest is you know 839 now we might be able to use golang alpine notice that's 300 and so let's do that let's rebuild and do golang al pini and again i'm not going to work with any specific version and let's call this um you know what um i would like to modify my application one way and that is going to be to see which ports it's running on and so um hello i'm starting on sgb server on port percent v and then let's do port so we kind of see which port we're starting on which is whatever port was configured because remember we parse flags okay um and so i'll call this let's control c and let's oh we should remove our existing application because um docker rm we should remove the application that we're running that container okay um so let's clean up and do docker upgrade again and if i run this it's gonna do the same thing because it's a new images building has to download all right so let's do this again and no i do not want you to edit anything and notice now our final image is much smaller than the 860. we're using alpine which is much smaller so this is good because if you're pushing your image to an image server maybe they have limitation or they charge you for how much data you store or even just the mere fact that when you go to startup why use much larger image if you can get away with a smaller one right so uh when it comes to containers and application you know if you can get away with a smaller size i'm doing the same thing um go absolutely go for it and so let's see if it actually works so we can do try running again so let's run our application oh we didn't give it a different tag okay and so there we go it's running and then i'll do log and this should show you that oh we're using yet the new application notice hp listening on port 8000 and you can do the curl command and same thing so our stuff is working just fine all right so this doesn't seem to be anything new compared to what we've done i've simply like i said just use an image as base that has go in it and just build our application in there so the one benefit now is i don't have to worry about noticing my source directory you don't see anything about that binary it's not there and it's built for the correct environment so that's good what i did tell you though is that we can separate our building um the container we used to build in from continuing we use the running and so the way we can do that is by doing this we can say that we need to use from go alpine this very small one as or a builder or build and you could give the tag essentially and so if you hover over this you can see that um nah tag out no alias they call this and so if you go to online documentation open documentation you'll see you can say from as name so you can give the name that's what is in name and so by naming this base as builder we can do all the stuff that we need to do for building which is all the way here and then once we get here we can say you know what from some other image and let's just call it go alpine also because that's pretty small and we can say from there we really need to be able to um run our application so that means that we need to do this sort of thing in this other container which is expose the port that we're going to be using for because this is this container here we could think of this i can call this as runner or runtime if i like but within this this image that we're going to build remember from every when you do from it says the base image and then it modifies it so we're saying use this base to build where we're going to create a work and actually copying our source code run the build command and that's great and then here we'll do from this guy we want to be able to say that we're going to expose this port and we have a working directory and how do we get the binary that we built remember the binary build is in this directory um root source slash app1 how do we get that in this image it's a totally different image so what we do is we can say copy and with the copy let's open again and copy we can do copy copy copy and let's see there's a copy from optionally copy accept a flag from that can be used to set the source location to a previous build stage created with from as which is exactly what we're doing so we can do that so we can say copy space dash dash from and the stage that we want to copy from is builder right that's the name of the stage and the directory so no we're just saying that oh it's from this stage this previous stage here but the directory that we want to copy or the image the thing we want to copy is from root slash src slash app1 that's the thing we want to copy and we can copy it to i don't know anywhere we want right really but let's put it back in root for now now you know we're going to be boring and put it back in the root half one and what we should probably do is then set this as the path that we want to run with root slash app one okay so same path here is the same path we run with here okay and so that's all there is to it i mean it's really not that complex if you look at it we just separated the two things before we're essentially doing this um just this at the bottom here that's all we were doing before now we've introduced this part of building the um image within a builder application within a container and what we the difference here is now we have separated to two now you may say why separate the two well i sorry hinted that in introduction this second image will not have our code so if it's compromise or whatever our code is not there maybe our code is a lot of code it doesn't matter maybe we need one type of image for building because there are a lot of dependencies and then the runtime image is completely different with very few dependencies so for all those reasons if you don't need to have a bunch of stuff in your image why have it there it just um leads to more um surface for an attack right so let's just um do um docker rm to clean up or run an applicator application we have there we'll do docker build and this time we'll call it version two so we'll leave the other one around and so um you know what i can do is clean up this and then do um this that watch minus d and then if i do that we should see yep the previous one version one is like 320 and that's fine i don't expect the other one to be much smaller because we're still using alpine gold line alpine now i'll talk about something in a bit but we'll see so yeah there we go i know successfully copied over and so now we have a second version 2 which is slightly smaller and i'm guessing that's because we don't have all the code that any intermediate code or something i don't know um because we didn't really have to do a whole lot we just copy the only thing that's different is that we didn't have the code but the code wasn't that much for it to be like you know 14 megabytes difference but it is it's 4g make it right smaller and that's a good thing smaller or smaller ever by tanks um all right so now we can run our application with this new one and so let's do docker so let's clean up docker run and then we'll save version two of our application and let's run in and we can say docker log to make sure that it started and it started and it's listening and we can say curl and there we go our application is running so what have we done today we've shown that how you can build in one and within one dockerfile you can have a stage where you build with one image and then even within that same file you can copy artifacts or the result of your build or whatever work you're doing in that first stage into another stage and continue so you can do this as many time as you need to multiple stages if you have multiple stages built and the advantage here is one our build stage can have many more dependencies and all these other things than our execution stage and so that allows us to limit things now alpine is an as what is happening here is the gold team is using alpine um image as their base and adding all the cool stuff to it so let me show you that so if we go back to you know docker hub and you just pick alpine any one of them it's going to show you what they're doing and you can see it says from alpine and they have to add a bunch of things right they have certificates because alca pine is so small it just comes with basically nothing in it right let's do ctrl c here and then let's do docker image list [Music] and then if i do grab and i do alpine um you can see alpine latest and so on it's just like five point something megabytes these are very very small images the problem with them is however because they have so little in it and you'll see from what the go community has to do all these things they have to add to it in order to get it to be able to run go code and the reason for that is let's say we do this let's say we decided oh you know what we actually don't want because our runtime image actually has go build tools and ideally we don't really want that right um why have that runtime we're not running google command itself so why have it there we already built the application so ideally we should what we want is something like this is just use alpine and say hey just run our application well let me show you what happened there so let's try and do a docker rm remove our app because that's still running and then i'll do docker um build and let's follow three i'll clean up the screen and i'll run so if we were to do a watch command again and we look we'll see three wow this is amazing we're we took uh you know essentially a alpine image that's like 5.5 or 6 gig megabits let's say and our application is itself because remember go does static binaries right and there are even ways that you can make the go binary even smaller because it contains some debugging information so you can strip that out but it's still a static binary you can take it to anyone to anyone that could run into analytic system but this alpine is already a linux system right um i mean i can prove that i can say docker minus interactive minus rm to remove this container when i'm finished and i could say alpine and i can say sh and here i am inside of alpine right i can do ls i can do i don't know if they have ps because they don't install a lot or fps but you know what there's not much in there well here's the thing um i'll take this opportunity to go back here and do this i would say docker ps just get all the running containers and you can see the alpine one is running here so i'll do that and what i'll do is um in this directory i'll go to source and i'll see oos build this for linux so i'm doing this on my mac and i'll say docker copy copy this application i just built on my mac to this container this alpha linux container into the root file system so if i go back here now and do ls you should see i have that linux binary right and if i do file and i say app one assuming they have the file command they don't um so how do you add stuff to alpine well you use this uh app um apk ad and so maybe i can do apk add file command um let's see if it's gonna install it yep and so there we go and i do app one and it tells me it's an elf file so it is a linux file right and it's statically linked which we can see here we exactly it's a gold build right um so if i try to run this though app one look at that there you go it's it's running right well and it says it's listening now if we exit this and we try to run our docker run and we try to run our three remember three let's clear this up watch three is the image that we build the last image we build that says put our application and base it alpha alpine right the runtime image stage right and so if we do minus d and then we do this and then now we do docker log and this you'll see that's how it's running and so let's go back here ctrl c and do curl and there you go now what i was going to show you is that sometimes um i've seen where you build your application you copy it into an alpine use alpine as your final stage and then it does not work it didn't allow the executable to just run even when i log into the container and try to run it it didn't work so just be aware of if you see that happen just make sure maybe using the latest alpine now maybe i was using an earlier one that's why i didn't check the version because notice i'm just doing like alpine i stick in the latest one so but this is just goes to show you exactly what i started off saying is that you can use one um stage which is a much bigger one that has all kinds of tools in it for you and dependencies for you to build your code and then your runtime is something that's much much smaller okay so that's it um i know that's all for some people this is kind of slow the process that i take explaining everything but i make videos the way i like seeing videos make i like feeling like if i come away understanding the you know ins and out of it as best as i can or to a certain depth all right with that said thank you again if you can support the channel in whatever way you know make sure you subscribe um send another invitation to other people to join hitting that notification bell and of course you know looking at the patreon page or my paypal and other ways of contributing that would be very awesome thank you very much take care stay safe bye see you in the next video
Info
Channel: Vilito Exquisitus
Views: 513
Rating: undefined out of 5
Keywords:
Id: G2TWMoTcCXY
Channel Id: undefined
Length: 30min 19sec (1819 seconds)
Published: Tue Feb 16 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.