Vue 3 & Docker — Vite & Caddy and Essential Settings

Mustafa Çağrı Güven
4 min readSep 4, 2024

--

For some time now, I’ve been planning to write a blog post on using Docker with Vue 3, and it’s finally time to share my experience. 📝 After struggling with incomplete documentation and some tricky issues, I want to walk you through how to set up Docker with Vue 3 and Caddy the right way. By the end of this post, you will have a smooth and consistent development environment that’s easy to manage. 🚀

If you have tried to use Docker with Vue 3 and Vite and found yourself struggling with some issues, you are not alone!

Vite Configuration

One common problem is missing two crucial lines in the server section of the configuration: host and strictPort. Adding these ensures that your Vite server listens on all network interfaces and prevents the port from changing if it's already in use, which can cause issues when working with Docker. 🛠️ In general, there are tons of questions in StackOverflow or Github and they shared only one of them and the other one is missing. 🤦

Here’s a quick snippet to include in your vite.config.js:

export default defineConfig({
server: {
port: 5018, // 🔧 Change this to your desired port number
host: true, // 🌐 Ensures the server is accessible from the network
strictPort: true, // 🚫 Prevents the port from changing if it’s in use
},
})

Caddy Configuration

Create the Caddyfile in the caddy folder, ensuring there’s no file extension. 📁 Caddy’s reverse proxy and automatic HTTPS setup make managing local domains simple and secure, which is a huge time-saver during development. ⏱️

caddy/Caddyfile

{
local_certs
}

mevn-github.localhost {
encode gzip
reverse_proxy client:5018
}

server.mevn-github.localhost {
reverse_proxy server:3320
}

compose.yml

name: mevn

services:
server:
build:
context: ./server
dockerfile: Dockerfile
restart: unless-stopped
env_file: ./server/.env
volumes:
- ./server:/app
networks:
- mevn

client:
build:
context: ./client
dockerfile: Dockerfile
restart: unless-stopped
env_file: ./client/.env
volumes:
- ./client:/app
networks:
- mevn
command: yarn dev -- --host
depends_on:
- server

caddy:
image: caddy:2-alpine
ports:
- 80:80
- 443:443
volumes:
- ./caddy/Caddyfile:/etc/caddy/Caddyfile
- ./caddy/data:/data
- ./caddy/config:/config
networks:
- mevn-github
depends_on:
- server
- client

volumes:
caddy_data:
caddy_config:
networks:
mevn:
driver: bridge

Here, we are defining our compose.yml file since we have 2 different structured folders, server and client. And, Dockerfile will not be enough for us for this time. 🔗

Additionally, using compose is always better for scalability 📈, so we will save some time soon. By the way, I am explaining the whole details here since there are at least a dozen documentation/videos for the details.

server/Dockerfile

FROM node:22.7.0-alpine3.19

WORKDIR /app

COPY package.json yarn.lock ./

RUN corepack enable && corepack prepare yarn@4.4.0 --activate && yarn install

COPY . .

CMD ["yarn", "start"]

Just a note, I am always using yarn instead of npm, and here as you see we are using the specific version for yarn: 4.4.0. It is not mandatory for us however you can have a look at the yarn’s documentation for the benefits for using the latest versions.

Also, there is a special note for the node version. I am just using the latest one here.

client/Dockerfile

FROM node:22.7.0-alpine3.19

WORKDIR /app

COPY package.json yarn.lock ./

RUN corepack enable && corepack prepare yarn@4.4.0 --activate && yarn install

COPY . .

The client-side is almost the same. Just the difference is that we are not running the command: yarn start or yarn dev here.

command: yarn dev -- --host

There are some dashes in the command that cause some issues and not work correctly in Dockerfiles. Therefore, we are running the command for the client in compose.yml.

Why Docker with Vue 3?

  • Consistency: Docker ensures your app runs identically across all environments, eliminating “it works on my machine” issues.
  • Caddy for Simplicity: Caddy automatically handles HTTPS and reverse proxy configurations, making your setup cleaner and easier to manage.
  • Simplified Setup: Docker bundles all dependencies, while Caddy simplifies web server management, reducing configuration headaches. For example, you can use auth.localhost or dev.myProject or prod.myProject as a domain in your local machine which is integrated with your project super easily.
  • Built-in SSL: Caddy provides automatic SSL certificates, making your site secure with minimal effort. Like https://auth.localhost or https://dev.myProject or https://prod.myProject
  • Isolation: Run multiple projects with different configurations without interference.
  • Smooth Deployment: Docker and Caddy work together to streamline deployment, ensuring your app behaves consistently across environments.

And that’s a wrap! 🎉 We have covered Docker with Vue 3 and Caddy from start to finish. If you have made it this far, I hope this guide has cleared up any confusion and given you the confidence to tackle your own setup. 💪

I found a great video on Docker that dives deeper into using Caddy, and I would recommend checking it out for even more insights. Thanks for reading, and I am excited to hear how your projects turn out — feel free to reach out with any questions or to share your experience! 🙌”

--

--

Mustafa Çağrı Güven
Mustafa Çağrı Güven

Written by Mustafa Çağrı Güven

Comp. Eng. @Sabancı University Graduated '11 / Senior Frontend Wizard / Vue.js 3 / Node.js / Express.js / MEVN / Nuxt 3 / Clean Code & Open Source ❤

No responses yet