Dockerize Nuxt.js
Part 1 Nginx & MySQL
Last update
- Structuring Nuxt app for Docker
- Creating Dockerfile
- Creating docker-compose
- Configuring Nuxt
- Building and running image
- Setup and configuration of Nginx
- Setup and configuration of MySQL
- Building image for production
- Testing production config
- Next steps
Structuring Nuxt app for Docker
It's not necesserary to change the default nuxt structrure but it's very recommended. When your app grows the more important a proper docker stucture proves to be usefull. Additionally it's very easy and takes only a minute.
Create a container folder for docker services and paste your current app into it. Next preperate nginx and mysql empty folders. Doing this will enable you changing default configuration of Nginx and MySQL or any other service just by proving proper conf files.
Creating Dockerfile
Inside the root of your app create a Dockerfile. This file is responsible for bulding and running your app on designated port. Nuxt.js is a Node.js app so when creating a new image it's very convenient to inherit from a node image and build on top of that. Take a look at the body of the Dockerfile. There are a few things that may be not clear if you haven't use Docker before. I will explain them now but if you are already familiar with how Docker works just go the the Docker compose section.
FROM node:12.16.3-alpine3.9
RUN mkdir -p /var/www/dockerize-nuxt/nuxt-app
WORKDIR /var/www/dockerize-nuxt/nuxt-app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 3000
ENV NUXT_HOST=0.0.0.0
ENV NUXT_PORT=3000
CMD [ "npm", "start" ]
Add .dockerignore file with at least this minimal content:
.git
.gitignore
node_modules/
Dockerfile explanation:
The first line it's a command for building a node.js image. I recommend you not to use the often proposed in many tutorials the latest version as it can lead to unexpected behaviour. Choose a specific node version and test it before going to production.
Next there are commands for making a new folder for your Nuxt app and changing working directory to this newly created folder. This working directory is exacly the root of your app inside the docker image and you can execute any command that you used to execute before dockering your app (assuming that all dependencies are installed).
Forth and fifth commands respectively copies package.json files with your app dependencies and install them (notice that it's usual step when bulding a new app on production or from repository).
Then copy (COPY . .) the rest app files from current host directory into current working directory of the docker image (/var/www/dockerize-nuxt/nuxt-app). The next RUN npm should be obvious now.
What may not still be clear is expose and next two commands. Expose tells docker service on which port forward your running app to the host system. Remember that your app is actually run by docker not the host system. The host system only runs the docker service. ENV NUXT_HOST and PORT commands (actually envoronment variables) declare internal docker address and port where the app is running, 0.0.0.0 means whole range. These are important because you will run other services which uses different ports that communicate one another in docker service. It works exacly the same as services in your host system but it's separated from your host and this is the core idea behind the docker itself. The only things which is shared between docker and the host is kernel.
The last one command starts our app. You can pass here any command to execute after building process. It's high time to test wheather your app is running properly as a docker image. Let's build and run it!
Creating docker-compose
Create a docker-compose.yml file in the container folder (not the root of your app). From there you will be able to configure and connect other services like MySQL or Nginx. First declare your app service in that way (change folder name and service name for yours). Build should points at the folder with your nuxt app.
version: "3.7"
services:
nuxt-app:
build: ./nuxt-app
container_name: nuxt-app
restart: always
ports:
- "3000:3000"
command: "npm run start"
networks:
- nuxt-network
networks:
nuxt-network:
driver: bridge
Configuring Nuxt
Before building the image, you have to change a little bit in .env nuxt file. Find HOST declaration. Just replace 127.0.0.1 (or localhost) for name of your service declared in docker-compose.yml.
HOST=nuxt-app
In that way an internal Docker address wil be passed to your Nuxt.js. You are ready to build and test your docker image.
Building and running image
Go to the container folder where docker-compose.yml file resides and type:
docker-compose up --build -d
Image building process takes a while. After building thanks to -d parameter your image will start running in the background so it won't block your console. You can check wheather the image is running by typping:
docker ps
or go to 127.0.0.1:3000 to check if your app works.
Setup and configuration of Nginx
Let's add Nginx service to docker-compose.yml.
services:
web-server:
image: nginx:1.17.10-alpine
container_name: web-server
volumes:
- ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
- web-root:/var/www/blowstack
ports:
- 80:80
networks:
nuxt-network:
depends_on:
- nuxt-app
restart: unless-stopped
volumes:
web-root
We need to configure the server and now it's time to use the empty nginx folder previously created. On the Nuxt.js website there are multiple proposed configs for Nginx but they don't cover docker example. To make it workable with Nuxt we need to pass to the config docker internal address (highlighted with violet). Below full minimal config. Create a folder named conf.d in the empty nginx folder and then create a file named default.conf. Finaly pass the below configuration to the conf.d file, changing services names if necessary. You should also definetly change server_name to your domain.
If you use local environment don't forget to add in hosts file appropriate line like:
127.0.0.1 local.blowstack.com.
default.conf
upstream docker {
server nuxt-app:3000;
}
map $sent_http_content_type $expires {
"text/html" epoch;
"text/html; charset=utf-8" epoch;
default off;
}
server {
listen 80; # the port nginx is listening on
server_name local.blowstack.com www.local.blowstack.com; # setup your domain here
gzip on;
gzip_types text/plain application/xml text/css application/javascript;
gzip_min_length 1000;
location / {
expires $expires;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 1m;
proxy_connect_timeout 1m;
proxy_pass http://docker;
}
}
Once again go to the container folder where docker-compose.yml file resides and type:
docker-compose up --build -d
Check if the app at your local domain works and move to the MySQL section.
Setup and configuration of MySQL
The last service created during first part of this post will be MySQL. It's very similar to the Nginx one but we need to also change DB_HOST parameter in .env nuxt file. Additionaly if you want overwrite default config just paste it to the mysql folder in a smilar way that we did with Nginx. On purpose I declared 3307 ports because you probably already have running MySQL on 3306 port localy and it will cause errors then.
DB_HOST= db-mysql
You can change db-mysql: to any other descriptive name. This is the name we will use in docker-compose.yml file to define MySQL service and it's need to be the same in both files.
services:
db-mysql:
image: mysql:8.0
container_name: db-mysql
command: '--wait_timeout=28800 --default-authentication-plugin=mysql_native_password'
volumes:
- "mysql-data:/var/lib/docker/volumes/blowstack/mysql"
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: database_name
ports:
- "3307:3307"
restart: always
networks:
- nuxt-network
volumes:
web-root:
mysql-data:
Go to the container folder where docker-compose.yml file resides and type:
docker-compose up --build -d
Check if your app communicates with MySQL.
Building image for production
You already have working solution of your app in docker service. But you still doesn't have an image which can be easily distributed. We just built nuxt-app service from local files and it's not docked in the hub, it's still totaly local. You still need local files to change and rebuilt your image. It's time to create and push image of your app to the Docker registry. Notice that we didn't use Dockerfile for Nginx or MySQL services, we just declared ready images from Docker hub repository. We are going to do exacly the same with your app but moreover you will keep it on the private repository accessible only for your team.
First stop all containers:
docker stop $(docker ps -aq)
Change directory to root of your app where Dockerfile resides and type (change nuxt-app for the name of your app):
docker build -t nuxt-app .
In the meantime go to the docker and create new private repo.

You will be informed about the CLI way of pushing your new image to this repository.

In my instance it will be done that way:
docker tag nuxt-app:latest blowstack/nuxt-app
docker push blowstack/nuxt-app:latest
Testing production config
Change nuxt service section in docker-compose file. Replace build by your newly created image
nuxt:
# build: ./nuxt-app
image: blowstack/nuxt-app:latest
Build all images once again based on the changed docker-compose.yml file.
docker-compose up --build -d
Test if it's working in the browser.
Congrats! From now on you can easily commit changes to your nuxt-app image, push to the registry and run anywhere in minutes without complicated configuration.
Next steps
You can add any service to work with your nuxt image. In the next parts we will cover more sophisticated services implementations and solve some problems which can cause you a headache when dockerizing Nuxt.js app.