We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
Daniel Amber · 9.5K views · 282 likes
Analysis Summary
Worth Noting
Positive elements
- This video provides a highly practical, step-by-step configuration for the 'tools.build' library and Dockerizing ClojureScript, which is often a point of friction for functional programmers.
Influence Dimensions
How are these scored?About this analysis
Knowing about these techniques makes them visible, not powerless. The ones that work best on you are the ones that match beliefs you already hold.
This analysis is a tool for your own thinking — what you do with it is up to you.
Related content covering similar topics.
Transcript
hey what's happening guys in this video we're going to take a look at deploying a full stack closure application so let's get started [Music] cool so before we get started the way that we're actually going to build this application is by creating a Docker file which will build us our jar file and what we're going to do is use GitHub actions to SSH into a linode server pull down our repository and compile the jar file and run it so let's just get started the first thing I want to do is pull down this repository of our full stack Java application I've made videos on how I built this basically it's a URL shortener so we just put a URL in a input box and it will give us a short URL back and when we click on that URL we'll get redirected to the original URL so let's just clone this get clone and I'm gonna clone it into a directory called short URL deploy and I'm going to CD into short URL deploy and I'm just going to remove the get folder the get directory awesome then I'm going to open it in vs code so the first thing that I want to do before we get actually into anything is update our environment variables I was using plan scale to create a database well I use pencil to create a database because you can create a free database there so I'm just going to add new credentials there so I'm going to click connect here new password and I'm just going to copy this new password and username and now we should have a working database then let's get started on actually creating that jar file so the first thing I want to do is go to tools.buildguide and this is how we can build our jaw file and configure the build using closure code so the setup is really easy we just need this build Alias which I'm going to copy out of here and go to devs.edn and add it to our aliases map [Applause] and then we just need to replace this library with the right tag insha so let's go to the top here click on tools.bull this will take us to the GitHub repo and here we can copy the library so go back to our project and replace this and then I'm going to create a new file here I'm going to call it build.clj and they've actually given us pretty much everything we need to compile an Uber job in this documentation we just need to copy from compiled Uber job application build we just copy this build paste it in here and here we can see we have a namespace build and this is looking for the build namespace and what this script does is basically use this tools.build library to compile a Java file for us we don't need this Library version we don't need this version It's just used for the naming of this file which we're actually just going to call standalone or we call it app standalone and if we go down here we could see that it's looking for a main function inside of this namespace we obviously don't have this namespace so let's use the namespace that we do have and if we go to show if we go to Source clj call this is where I want to add the main function and this will be the starting function that starts our application so let's go to build.clj and use our short URL dot core namespace and now let's create that main function in here so in order for that function to be executable we need this gen class form inside of our namespace and then we pretty much want to run the start function which starts our server and we want to run that inside of our main function so diff in hyphen main you need that iPhone name and we run the start function start our server and let's just add like a print line here to say starting app and I also want to I don't want these two forms to just run when this file evaluates so I'm just going to put those inside of a common form cool and I actually think we have enough to run this build tool so let's open up our terminal and the way that you can run a build tool is by running clj closure hyphen t for the tool then the tool is gonna be we need to do a hyphen it's this build tool so we run build and then we need to reference a function within build.crj and we're going to reference this Uber function so let's run Uber and this should build us our jaw file and there's an issue in our devs.edm file let's check save we had an extra curly brace so now let's re-run this awesome it looked like it worked so if we check our directory we should have a Target folder we do and there's our jar file so to run that jar file we just need to run Java jaw and then the path to our jaw file which is this red and now we should have it running on Port 3001 because that is the port if we check our star function that's the port that our app starts on so let's go there go to localhost 2001 cool and it is working Rad but now if we check our Network tab we can see that we're getting a 500 on the fail icon.ico because we don't have one so let's just add one quickly um let's close this I am just going to go to resources assets add a new folder here call it images and I'm going to paste the fave icon in there I'm just going to use I've got a fave icon which is just an alien emoji so it's added to this directory and now let's go to our index.html and it's reference that fave icon so to do that we just go link relationship and that is icon and then type is I think it's image X icon and then the href is gonna be assets forward slash images forward slash Dave icon dot icon and if we go to this will work because if we go to core.clj we are just serving everything in our assets directly so that'll be found and then there was another issue if we go back here where we can see that shadow clgs is trying to connect to this application but this is a production application so we want to run like production JavaScript so let's compile our JavaScript into production JavaScript so let's remove JavaScript from our assets directory let's delete this and let's open our terminal close our running application and if we go to Shadow see I'll just use the guide we can see to generate production code we just run shadowcljs release and then the build ID so let's copy this out paste it in here now I build our our build ID is called app and you'll see that in the go to shadowcljesta Eden this is our bold it's called app so if we run this oh it doesn't work so when I ran that I got this founder found exception and that's because I've got this error in it my devs.edan file where I close the this aliases map too early so I just need to move that to here save this and now I should be able to run Shadow cljs release app okay now we're getting that with dependencies are not are required but they're not available so I'm just going to run npmi and then clear this and then we can run shadowcljs release app again awesome so now in resources we'll have our compiled JavaScript so now if we build our jaw file again and we run that Java foreign this page cool it's working but we have no Styles so let's just go back and see why that is so if we go back to our index file it's very clear while we have no Styles so let's just fix this up [Applause] then it's rebuild our Uber jar and then rerun it so rebuilding let's re-run it go back to our page refresh it yeah okay and it's working awesome first thing I want to do before we dockerize this build is actually let's do something out we don't want our CSS we want to like compile that when we build it so I want to delete this here and our JavaScript we don't want to have that we want to delete this and only have it when we build it so I'm going to add those to our get ignore those parts to our git ignore so we're going to ignore from resources forward slash public forward slash assets forces JavaScript and everything in that directory and we're going to ignore everything in the CSS directory cool then what we want to do is create a Docker file so a new file Docker file and we want to get we want to start this from we can actually go to the docker Hub page of closure and there is actually an image here for the build tool so let's go down here yeah tools.deps so we can copy this exposure tools depths and that can be our base image then what we want to do is we want to copy everything here from here let's go back to the image yeah we want to copy everything into user Source app so let's paste that here then let's compile our JavaScript so let's run npm install and we also need chatter crjs let's run npm IG shadow cljs and then npm install we want to run and then we want to compile the the closure script so we align shadow cljs release app [Applause] but now in order for these for these commands to work we actually need npm so we need to install node and to do that I found um some guy's comment on like just on GitHub so I'm just going to copy this and add it and this will install node version 14.18.1 cool then we also need to compile Tailwind so to do that what we need to run is MPX Tailwind the input file and that would be this global.css the output file and that will be I think it was resources forward slash public forward slash assets for slash CSS forward slash out dot out output.css and then we want to add this Minify flag let's see if that works doesn't oh okay you don't it's not out it's oh so let's do this cool and that will compile our CSS so let's copy this command here and add it to our Docker file so let's do that first and then finally we can compile the ubuja so we'll just go run cljt codon build Uber and that will build as the jaw file and then we just need to run that Java so we can run command Java hyphen jar and then the pause to that file which is Target forward slash app Standalone dot jar and this should be our Docker file so what I want to do is actually create a Docker compose file to run this so Docker compose and then we need a version here and I'm just going to use 3.9 then we're going to have services and the first service is going to be say app and we're going to build our doc files sitting in our main directory so we can just go build Dot and then it's just map a port let's map ports 8080 so that's our local port to port 3001 and that's where our app is running so now we should be able to run just make sure you've got darker running so Docker compose up app and we're getting an issue with this Shadow cljs command but I actually think we can run it with MPX so let's go back to our Docker file and instead of doing this Global install let's run npmi and then MPX Shadow cljs release app and let's try rebuild this and now we're getting this that's required gen of JavaScript dependency react is not available so let's add that to our package.json yep let's add that here react and add the version you can do this and now let's try and do this again [Music] oh damn okay I'm already so it did work but I'm already have a binding for port 8080 running so I'm just going to go back to Docker compose and I'm just going to change my Portia to be like port 8085 and then let's just rebuild this like compose up app when I've revealed it rerun it cool and looks like it worked so let's go to localhost Port 8085 that looked like it worked let's copy a URL and paste it in here click shorten URL it shortened the URL let's click it awesome this app is working with uh our Docker build so now let's create a server and let's pull down this repo on that server and do the same thing on a server to have this running on a server in the cloud I'm going to be using the node for this the reason I'm using the node is because I got some free credits um thanks to Lex Friedman and let's create a node I'm going to go to Marketplace and I'm going to search for Docker here click Docker and let's check what we want for the setup don't need any of this select an image select an image I'm going to choose Debian 11 a region I'm going to choose London cool you can obviously go for um the dedicated 512 gigabyte server but I'm for now I'm just going to use this nanode one gigabyte five dollar a month one and yeah root password I'm just going to suggest a strong password and copy it create a lineard then there's SSH into that server Goods SSH into that server then yes let's put the password in yeah and we end the server so what I want to do now is pull down a GitHub repo which we don't have so I'm just going to go back to our product so I'm just going to go back to our project let's stop this and for our production server I don't want this to run on Port 8085 I wanted to run a port 80. and I want to have it have the flag of I think it's restart always and I want to actually have an EnV file and I'm going to call the file name.emv we don't have that right now uh because I don't want to be pushing these live credentials so what I'm going to do is this env.edn actually wanted to be like a Dev thing so what I'm going to do is git ignore this so get attributes or get ignore and Let's ignore env.edn and then what I want to do is we need to go to Source clj EnV and make sure that if this env.edn file doesn't exist our app doesn't blow up so to do that you just need to run when we need to check if dot exists and then we need to run closure dot java.r forward slash file and then the file name which is env.edn if that exists then we'll do this otherwise will return a blank map and let's put this in the right place cool and that will cater for this file not being in our repo and what we could do is we could duplicate this and make like an example or env.edn.example so I actually still want this data so I'm just going to copy it out of here um open Sublime and just paste that in there and then this example file we'll just have I don't know empty string for well we can keep the host we can just take up the username and password so user and password and yeah let's make this a good Depot so I'm going to get a net get at dots and then give commits a.m and I'm just gonna call this a net so let's so let's make a new repo I'm just going to go to my GitHub page how to trees create a new one and I'm going to call this short URL deploy create Repository and let's add this origin go back here and it's the push it before you refresh this cool so now we've created our GitHub repo and I want to pull this on else server here so what I'm going to do is generate an SSH key so SSH Keygen so after we create it let's copy it then we can go back to our repo go to settings and if we go to deploy keys you can add a deploykey cam paste this in here and give it the title of linode and add key sweet so now we should be able to clone this repo well it's a public repo but I mean if this were private that's what you would do so let's go just get clone sweet and now we should be able to CV into short URL deploy and we should be able to run docker compose app app okay couldn't find a EnV file so let's just make one so we can go touch dot EnV edit that so Nano dot EnV y cool once you've done that we can save this file [Applause] then we should be able to run Docker compose again black compose up app okay so we're getting this command I found tailwind and that's because I made a mistake here we actually need to go back to our Docker file and it's not Tailwind it's Tailwind CSS save this then it's good commits I am fix Docker file push now we should be able to get who and let's retry that cool now we're getting another error here env.clj Okay so ah this here is that this function is not exists it exists that's why you should test stuff before you just deploy it but anyway let's retry that so git commits and fix EnV file okay push then let's pull again here pull and we can retry that deploy hopefully for the last time cool so it looks like it actually worked so we see the starting apps the starting app print line now if we go to linode and we copy the IP address and we paste it in our browser we see our application so let's just copy this copy this paste this it's working awesome so that's all cool but I want this to actually deploy every time I just push to that Branch so what I'm going to do is I'm going to stop this and let's look at using a GitHub action to do that so to use a GitHub action all we need to do is make a new folder call it dot GitHub and inside of that we want to make another new folder called it workflows and I'm just going to call this one deploy.yaml and essentially all I really want to do here is SSH into my Linwood server and do exactly what I would have done manually to do that we can Apple boy has made this SSH script for us let's just copy it out so we can just copy this paste this we want this on push to main so I think it's on push then branches then main I think that works okay we don't want to run who am I what we want to run is a multi-line script and this will basically City into short URL deploy then we're going to get pool and then we need to run docker compose app app we can add a bull tag here and we also want this to run in the background so to do that what we need to do is add a demon flag here and now we need to say give it our host a username and password well this port so the SSH Port is going to be 22. the host is going to be that IP address now we just need to give it a username and password we can actually say I think the username would be root and let's give it a secret password so let's go back to our Reaper settings secrets and we'll add a password Here and that's going to be the password that we gave out the node server cool I'm just going to copy that password in here now I think all I need to do is get commits am updated workflows well let's get add dot then run git commit and added workflows hit push now I think we should see a workflow running if we go to actions because our workflow is here but it didn't run let's just see why and that's because we need a space here so it's fixed workflows I also I also just noticed one thing I miss built you URL on this repo it's ulr which is fine let's make like I did it on purpose so we need to CD into short u l r deploy and let's try this again um fix workflows get push now we should have an automated deployment cool and it's running so we have an issue didn't work let's just see why I think it's possible that this host needs to just be the IP let's try that cool and this actually looks like it's working so I'm actually going to just make a change so we can see this change happen in our on our site I don't know let's go to our source cljs are cool and let's change the color here so instead of BG pink 100 maybe we can do 500. and it's more pink push that and now we should see another build start so if we go actions we should see another workflow running which is more pink and let's see this working cool and that build successfully Ran So now if we go to short URL app and we refresh this we got a more pink application and let's copy this URL paste it in here click shorten URL click this URL and the redirect works cool and that's just one way to deploy a closure application you could if you wanted to in your pipeline instead of sshing into a server and then building the image on your own server build the image in the pipeline push that to Docker Hub or wherever you want to host that image and then pull that image onto your onto your server and deploy it there's many ways you could use kubernetes or you could you could deploy it in another way but this is like this is a nice simple way to get up and running deploying your closure application I hope you guys enjoyed this one see you in the next one bye
Video description
Build and deploy a Clojure app by: Dockerizing the CSS, ClojureScript and JAR build Using GitHub actions to SSH into a server pull the repo then build and run the created image. GitHub Repo: https://github.com/danownsthisspace/shorturl-deploy Starting Repo: https://github.com/danownsthisspace/shorturl-app Previous videos: Video 1 (Build the back-end): https://www.youtube.com/watch?v=0mrguRPgCzI Video 2 (Build the front-end): https://www.youtube.com/watch?v=V-dBmuRsW6w ---------------------------------------------------------- Tools used in the video: Planet Scale (MySql host): https://planetscale.com/ Linode (Server): https://cloud.linode.com/ SSH GitHub Action: https://github.com/appleboy/ssh-action Node in docker container: https://gist.github.com/remarkablemark/aacf14c29b3f01d6900d13137b21db3a?permalink_comment_id=4279765#gistcomment-4279765 Shadow CLJS: https://shadow-cljs.github.io/docs/UsersGuide.html Tailwind CSS: https://tailwindcss.com/ Clojure Docker Image: https://hub.docker.com/_/clojure Clojure tools.build: https://github.com/clojure/tools.build --------------------------------------------------------------- Clojure Development in VS Code using Calva: https://calva.io/ -------------------------------------------------------------- 00:00 Intro 00:10 Deployment overview 00:29 Setting up the project 01:16 Adding environment variables 01:48 Create uberjar using tool.build 09:58 Dockerize build 13:39 Creating a docker-compose file 16:09 Create Linode server 17:22 Create Repo and pull it on Linode server 21:48 Create .env file on the Linode server 22:11 Fix dockerfile issues 24:01 Set up continous deployment using github actions 28:41 Test deployment