Development setup with Nuxt, Node and Docker
Hi there, in this article I will quickly walk you through my development setup with Nuxt, Node and Docker.
First things first: Although this article alone might be interesting for you, it’s part of a whole series on How to create a fullstack web app with Nuxt, Vue, Node, GraphQL and Docker. If you struggle understanding the whole picture and you just need a red thread through all the puzzle pieces of a modern web app you will find the other articles there.
Please note: I am not a Docker expert, but this setup has proven to work for me. If you have some improvement proposals feel free to let me know in the comments.
Two services, one git repository
To keep things easy but also modular I will split my code into two services:
- Server (Node)
- Frontend (Nuxt)
Those services will be decoupled from each other so I could easily move them into another repository. For development however it’s much more convenient to keep those two services in a single repository, so I don’t have to worry about keeping those services in sync.
Server
Alright I assume you already created a repository for your project. Now create a folder via mkdir server
within this repo. cd
into that folder and run npm init -y
to get a basic npm module setup. Create a file named src/index.js
and point the main
property in your package.json
to this file. For testing purpose let’s now put a simple console.log('Server running');
into our src/index.js
.
Automatic reloads
When you change something in node you normally have to restart the node server, which is really annoying in development. To our rescue there is a really nice package called nodemon
that watches your files and automatically restarts the node server upon changes.
npm install -D nodemon
- add
"dev": "nodemon src/index.js -e js,graphql,gql"
toscripts
of yourpackage.json
This installs nodemon
to your devDependencies and watches all files with the .js, .graphql and .gql extension.
Run the server
Alright our server should already be done. I hope you also added node_modules
to your .gitignore
;)
To start simply run npm run dev
and you should see your console.log
. Also if you change anything in your src/index.js
it should be automatically restarted.
Frontend
For our frontend we will be using Nuxt which is a Vue framework for server side rendering.
Now let’s go back into our projects root directory and create a new folder and cd
into it via mkdir frontend && cd frontend
. This time we can make use of the scaffolding CLI tool provided by Nuxt. So let’s run npx create-nuxt-app .
. The “dot” here is important because that tells the script to create the project in the current directory.
Run the frontend
So to run the frontend you can also simply use npm run dev
because that script is already provided by Nuxt. Also Nuxt installed a webpack
server that handles all the reloading stuff for us. If you setup everything correctly it should look like the screenshot below.
Combining the services with docker-compose
So now we have two services setup. To run those without docker-compose
we would have to execute npm run dev
in both of them. I am not going to explain every benefit of Docker, because there is also a controversial discussion between developers if you should use Docker for development at all. For me the benefits are:
- You don’t have to start every service manually
- You don’t have to remember how to run those services
- You don’t need to care about different versions
- You don’t need to setup external services on your machine (like database)
Please note: We are going to mount volumes for development, which might be a little bit slower (especially on Mac as I heard, never tried on Linux) than if you start your services without Docker. That’s something I can live with. If you have any suggestions to speed up things your comments are very welcome.
Why docker-compose?
In my opinion docker-compose
simplifies Docker heavily which is quite nice in development. We can just setup a .yml
file, put our whole config into that file and then simply run one docker-compose up
command to execute every service defined in that config.
Setup docker-compose
So to setup docker-compose
you can simply create a docker-compose.yml
file. First we need to define a version of docker-compose, in our case version: "3.7"
. Then we define services
, so a frontend
and a server
service.
Frontend service
So let’s define the frontend service.
frontend:
image: node:10.15.1
command: npm run docker
volumes:
- ./frontend:/usr/src/app
working_dir: /usr/src/app
ports:
- "3000:3000"
environment:
HOST: 0.0.0.0
First we define an image
that we want to use, in this case node
with version 10.15.1
. You can use every image hosted on DockerHub or also define a local image. For development we just want to make sure node is available in the same version for every developer.
Then we define a command
to run when we start the service. We define npm run docker
. So also make sure to add this script to ./frontend/package.json
as "docker": "npm run dev"
.
Then we mount everything in ./frontend
to the /usr/src/app
folder in our container that is also defined as our working_dir
. That makes sure our source files are always available in our container.
Also we need to forward ports. Our nuxt app will run on port 3000 within our container, but this port is not yet available on our machine. If you define 3000:3000
docker-compose will forward port 3000 on our machine to port 3000 in our container.
Last thing is the environment
variable HOST
. Nuxt needs this variable when started from a container, otherwise you won’t be able to reach it.
Host 0.0.0.0
is designated to tell Nuxt to resolve a host address, which is accessible to connections outside of the host machine.
Please note: Even though Nuxt might show something like Listening on: http://172.23.0.2:3000
it should still be available under http://localhost:3000
.
Server service
Now let’s define our server service.
server:
image: node:10.15.1
command: npm run docker
volumes:
- ./server:/usr/src/app
working_dir: /usr/src/app
ports:
- "4000:4000"
I won’t go into detail on this because it’s basically the same as the frontend config. We are also using npm run docker
as our command
so don’t forget to set this up for the server as well. This time we use port 4000
which is not yet accessible because our server does not listen to any port right now.
Running the services
Just do docker-compose up
in the root of your project and docker should spin up both services in parallel.
Dockerignore
To increase performance of your containers you should add a .dockerignore
file to your ./frontend
and ./server
directories. These files tell Docker to not copy specific files into our container. Both files should contain node_modules
. Frontend should also ignore .nuxt
.
Working code example
Although I added most of the interesting lines of code directly to this article, it might be more convenient to browse the whole source code on Github. You can find all the code from this article on this branch. You will always find the final state of this series in the master branch.
Final words
So that’s it for this part. We have working development setup using docker-compose, Nuxt and Node. If you are curious to know how to add more features and concepts to this server follow me and i22. Also keep an eye on the overview of this series:
What’s next?
After we setup Docker for development we want to setup a Continuous Integration pipeline using Docker containers. I will publish an article to explain this soon, so make sure to follow.
Marc Mintel is a senior frontend developer at i22.