Intro 💅[THIS IS A VERY OUTDATED ARTICLE THAT I WILL REVISE SOON]
Our awesome friend Natalia Tepluhina coded our Vuetiful Nuxt SSR website: (https://vuevixens.org). We are all super happy and proud about it. She can totally guide you through all the development details, I will only take our website to show you how easy it is to pack it in Docker and talk from the DevOps perspective of Vue Vixens.
Before getting our hands dirty (or not!), I'd like to quote the official documentation of Vue.js on Docker and an awesome take on DevOps culture:
Effects of DevOps
The adoption of DevOps culture, tools and agile engineering practices has, among other things, the nice effect of increasing the collaboration between the roles of development and operations. One of the main problem of the past (but also today in some realities) is that the dev team tended to be uninterested in the operation and maintenance of a system once it was handed over to the ops team, while the latter tended to be not really aware of the system’s business goals and, therefore, reluctant in satisfying the operational needs of the system (also referred to as “whims of developers”).So, delivering our Vue.js app as a Docker image helps reducing, if not removing entirely, the difference between running the service on a developer’s laptop, the production environment or any environment we may think of.
No better words to express the need for all of us to be part of it. Without this meaning you having to change your specialty, being aware of the "other side" of the process can only be to your advantage. Having said that, I'd like to quote the Vue.js cookbook one more time:
So, creating a Docker image for our Vue.js app is a good choice here because that would represent our final build artifact, the same artifact that would be verified against our continuous delivery pipeline and that could potentially be released to production with confidence
This is obviously when applicable. Docker like fries, doesn't always work with everything. Assuming it is the case that going forward this way applies to you, or that you're interested on how to get it done... let's get started!.
Let's get it started 🎵
⚡️Pre-requisites:
Provided that you have your app ready, you need the following installed in your local machine/server:
⚡️Folder structure
I created a different folder structure for this case. My local folder for the Vue Vixens website is "website". Inside that folder, I created a sub-folder and called it app and moved the whole app in its entirety to that folder.
Then, created another sub-folder in website and called it nginx. This structure is to help us build a whole image of our app with its own nginx container so we only worry about starting and stopping the app without having to configure nginx and pm2 separately to keep it alive.
This is how my folders look like.
⚡️Creating a Dockerfile
In our app folder, create a file and name it Dockerfile. This a text document that contains all the commands a user could call on the command line to assemble an image. And it has no extension.
Our Dockerfile:
FROM node:10.7
ENV APP_ROOT /src
RUN mkdir ${APP_ROOT}
WORKDIR ${APP_ROOT}
ADD . ${APP_ROOT}
RUN npm install
RUN npm run build
ENV HOST 0.0.0.0
Understanding our Dockerfile
- In this file we specify the node version we want our container to run. That's entirely up to you.
latestis also a valid tag. - It is also specified the app root directory and then the commands we run to build our app.
- The host is set to
0.0.0.0to give full external access to the app container.
⚡️Docker Compose
According to the official Docker docs, Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application's services. Then, with a single command, you create and start all the services from your configuration. (...) Run docker-compose up and Compose starts and runs your entire app. (Now we know why i love compose so much! 💁♀️)
Our compose file is located in our root website folder:
Let's take a look to our docker-compose.yml
version: "3"
services:
nuxt:
build: ./app/
container_name: vuevixens-website
restart: always
ports:
- "3333:3333"
command:
"npm run start"
nginx:
image: nginx:1.13
container_name: vuevixens-nginx
ports:
- "80:80"
volumes:
- ./nginx:/etc/nginx/conf.d
depends_on:
- nuxt
Understanding our docker-compose file:
- Version: We are using the latest compose version which is
3 - Services: Specify the set of services our app is composed of. In this case:
nuxt.- Build: These are configuration options that are applied at build time. Can be specified either as a string containing a path to the build context, or an object with the path specified under context and optionally dockerfile and args.
- Container_name: Your container's name.
- Restart: Restart policy to apply when a container exits (default "no").
- Ports: Expose ports. Either specify both ports
(HOST:CONTAINER), or just the container port (a random host port will be chosen). - Command: After we specified in our
Dockerfilethe install and build commands, then we pass the start command to run our app.
- Nginx: Another service we use, in this case it will be our server.
- Image: Tag or partial image ID. Can be local or remote - Compose will attempt to pull if it doesn't exist locally. In this case we specified our nginx version. The tag
:latestworks as well. - (Skipping repeated concepts, and going straight to..)Volumes: Specifies the volumes to be created as part of your app. This is what we will use our nginx folder for, to inject our nginx config to the container.
- Depends_on: Specifies the volumes to be created as part of your app. In this case our nginx is tied to our nuxt app.
- Image: Tag or partial image ID. Can be local or remote - Compose will attempt to pull if it doesn't exist locally. In this case we specified our nginx version. The tag
⚡️Configuring nginx
We are almost ready. Our last step is to configure our nginx. By default, our app will be running on port 3000, we will use nginx as a reverse proxy.
Lets go to our nginx folder and create the file: default.conf with the following contents:
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://vuevixens-website:3333;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
In location we connect directly with our app container, so whatever you call your app container has to have the same name in this file.
- We are ready to rock 🔥
Running your app like a boss 💪
Commit and clone your repo in your server. (The following instruction applies if you're running from your own computer)
- Cd to the
websitefolder - Run
docker-compose up --build -dand that's it!. The first time you run it, all the necessary files will be pulled from the docker repositories so it might take some time depending on your connection.
If you want to check everything went alright, run docker ps and you should see something like this:

That's it! hope you enjoyed the experience as much as I did! - A second part on adding a let's encrypt certificate is coming soon!


Discussion
You can do:
instead of:
You're totally right! :) Cheers!
Thanks for the article, it was very useful !
However...
When executing
I got an errno 137 at the nuxt building step.
If anyone encounters the same issue, I resized my DigitalOcean droplet for more RAM.
Maybe there's a better solution but that's how I got it working.
Have you checked that you add the
--prodtag when you run the nuxt build?I didn't! I'll try this. Thanks
Hi Diana,
I've follow your tutorial but since on port 80 I already have Apache so I've put Nginx on port 8080.
Everything is pretty straight to your file except for these lines:
docker-compose.yml
ports:
- "8080:8080"
nginx default.conf
server {
listen 8080;
Everything compiles okay but when i visit the site:8080 Nginx returns me 502 Bad Gateway.
Can you help me? Thanks! :)
For anyone who comes across this error, check to make sure your ports specified in docker-compose for the Nuxt container actually match what port that container is running internally. Normally Nuxt will default to port 3000 but Vue Vixens has changed that to 3333 in their config: github.com/VueVixens/website/blob/....
That change is just sort of assumed and not highlighted in the article since it's an existing project. So if you just fired up a new Nuxt project or imported an existing one that has the standard config, change your port numbers in docker-compose.yml and default.conf files.
I have the same issue!
Should we remove
node_modulesfrom docker images afternpm run build?node_modules so big(300MB).. I don't think it's a good idea if we build images with node_modules but I don't know How to solve.
For Vue SSR, we start process from server.js
even though we bundle all codes into dist folder, server.js not bundled.
If I remove all node_modules, server.js cannot works anymore because it
require('express')Great article! Love to see more
nuxt+dockersetups out there.I would also like to share our solution: github.com/wemake-services/wemake-...
It also features
gitlab-cito test and build your apps.Hi Nikita! that's awesome! thanks a lot!
Hi
I go to step by step your doc....I have a question after run docker-compose build && docker-compose up -d in terminal.... how to run my docker? what is server for show my web in localhost?
Literally 'localhost' since it's configured to show on port 80 :) sorry for the delay!
when iI want run docker-compose build && docker-compose up -d in my project ( my project consist of Nuxt JS and CoreUI : github.com/muhibbudins/nuxt-coreui ) I can't create docker and received Error :
ERROR: Service 'nuxt' failed to build: The command '/bin/sh -c npm run build' returned a non-zero code: 1
Can You help me for Dockerize Nuxt js with Core UI please?
thanks
Sure let me look at this!
I can't find you in slack...my username in your slack is zshahab91
github.com/alphacentauri82/nuxt-co...
I dockerised this, check it out for reference.
Hi Diana,
can you help me with this?
dev.to/johanneslichtenberger/oauth...
I have a branch for the OAuth2 authentication:
github.com/sirixdb/sirix-web-front...
I have added a detailed description how to setup the SirixDB HTTP-Server and Keycloak, but the problem currently is related to Docker Networking:
You might find the problem in my docker-compose.yml file. I'm relatively new to writing Docker and docker-compose files.
That’s neat - however, what about something like Ansible containers? Making it non-dependant on docker, instead any runtime/container Engine?
Definitely interesting options. There are so many different approaches! - I guess I can just start a series of deployment articles for frontenders. You gave me a great idea! 🤘
I’d love to collaborate if you want to do a series or anything? 👍
Hey Michael! are you on the Dev.To Chat? let's do something together!
Yep
Love it! I've also used Docker for spinning up a small server that can load the files produced from running
yarn generateso I can test out that the files generated will load properly in a web server environment.Great article, thanks! Can I change the service name from nuxt to something else?
Yes you may!
Great article, I was stuck trying to integrate Nuxt with Nginx and Docker and your guide made it really simple.
Thanks!
Nice article. But am having some errors after running
docker-compose up --build -d command;
ERROR: for jekalowa-account-nginx Cannot start service nginx: driver failed programming external connectivity on endpoint jekalowa-account-nginx (12ff3d36f94d71dda7bccb83efcbcdfac4df65c420d9a04124b23dc52c8c6e79): Error starting userland proxy: listen tcp 0.0.0.0:80: bind: address already in use
What should i do please?
Cool! Thanks a lot!!!
Greate Writeup! Diana.
Running docker in local dev environment is good, but if you can add a section on deploying the dockerised app in production environment then that would be wonderful.
Thank you very much for reading! there's an article coming about the CD/CI side, I promise! but for now you can actually pull your repo in your production server and run the commands to build and start your containers.
Hi,
thanks for the article! Does this setup include HMR of the nuxt app? Changes within the .vue files, but also in the nuxt config ?
Best
Vanessa
nuxt-start is almost 10 times smaller than nuxt since it doesnt have build tools , how can we use nuxt-start in production with docker?
Is it straight forward to add SSL with certbot to Nginx in this case ?
There are many ways to do it. I guess whatever suits you best :)
I followed this tutorial and it worked better for my needs. Check it out if you are having problems.
jonathanmh.com/deploying-a-nuxt-js...
Q: why use nginx instead of the built-in server?
+1
Yikes, i haven't updated this article. Many things have changed ever since!!