Compare commits

..

3 Commits

Author SHA1 Message Date
8e2cd7f9a1 Cleanup 2025-06-20 12:48:25 -04:00
fa25dde20f Add linkedin link 2025-06-20 12:46:12 -04:00
1696808c00 Fix devcontainer setup 2025-06-20 10:47:20 -04:00
11 changed files with 34 additions and 51 deletions

View File

@ -1,22 +1,15 @@
{ {
"name": "Fullstack DevContainer", "name": "Fullstack DevContainer",
"dockerComposeFile": ["../docker-compose.yml"], "dockerComposeFile": ["../compose.yml", "../compose.override.yml"],
"service": "frontend", "service": "backend",
"workspaceFolder": "/app", "workspaceFolder": "/app",
"shutdownAction": "stopCompose", "shutdownAction": "stopCompose",
"forwardPorts": [80, 8080], "forwardPorts": [80, 8080],
"settings": { "postCreateCommand": "/entrypoint.sh",
"terminal.integrated.defaultProfile.linux": "bash"
},
"mounts": [
"source=frontend_node_modules,target=/app/node_modules,type=volume",
"source=backend_node_modules,target=/backend/node_modules,type=volume",
"source=${localWorkspaceFolder}/backend,target=/backend,type=bind"
],
"postCreateCommand": "npm install && cd /backend && npm install",
"customizations": { "customizations": {
"vscode": { "vscode": {
"extensions": [ "extensions": [
"jripouteau.adonis-vscode-extension",
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"esbenp.prettier-vscode" "esbenp.prettier-vscode"
] ]

View File

@ -7,11 +7,15 @@ HEALTHCHECK --interval=5s \
# All deps stage # All deps stage
FROM base AS deps FROM base AS deps
WORKDIR /app WORKDIR /app/backend
ADD package.json package-lock.json ./ ADD package.json package-lock.json ./
RUN npm ci RUN npm ci
FROM deps AS develop FROM deps AS develop
WORKDIR /app/backend
COPY dev-entrypoint.sh /entrypoint.sh
COPY .env.example /app/backend/.env
RUN chmod +x /entrypoint.sh
ENV NODE_ENV=development ENV NODE_ENV=development
WORKDIR /app WORKDIR /app
COPY entrypoint.sh /entrypoint.sh COPY entrypoint.sh /entrypoint.sh
@ -21,14 +25,14 @@ ENTRYPOINT [ "/entrypoint.sh" ]
# Production only deps stage # Production only deps stage
FROM base AS production-deps FROM base AS production-deps
WORKDIR /app WORKDIR /app/backend
ADD package.json package-lock.json ./ ADD package.json package-lock.json ./
RUN npm ci --omit=dev RUN npm ci --omit=dev
# Build stage # Build stage
FROM base AS build FROM base AS build
WORKDIR /app WORKDIR /app/backend
COPY --from=deps /app/node_modules /app/node_modules COPY --from=deps /app/backend/node_modules /app/backend/node_modules
ADD . . ADD . .
RUN node ace build RUN node ace build
@ -36,8 +40,8 @@ RUN node ace build
FROM base FROM base
ENV NODE_ENV=production ENV NODE_ENV=production
WORKDIR /app WORKDIR /app
COPY --from=production-deps /app/node_modules /app/node_modules COPY --from=production-deps /app/backend/node_modules /app/backend/node_modules
COPY --from=build /app/build /app COPY --from=build /app/backend/build /app
EXPOSE 8080 EXPOSE 8080
CMD ["node", "./bin/server.js"] CMD ["node", "./bin/server.js"]

View File

@ -1,5 +1,6 @@
#!/bin/sh #!/bin/sh
cd /app/backend
echo "starting up..." echo "starting up..."
node ace generate:key node ace generate:key

View File

@ -8,10 +8,10 @@
*/ */
import router from '@adonisjs/core/services/router' import router from '@adonisjs/core/services/router'
import UsersController from '#controllers/users_controller' const UsersController = () => import('#controllers/users_controller')
router.get('users', [UsersController, 'index']) router.get('users', [UsersController, 'index'])
router.get('/', async () => { router.get('/', async () => {
return { return {
hello: 'hello', hello: 'world',
} }
}) })

View File

@ -5,10 +5,13 @@ services:
context: backend context: backend
target: develop target: develop
volumes: volumes:
- ./backend:/app - ./backend:/app/backend/
- node_modules:/app/node_modules - node_modules:/app/backend/node_modules
- frontend_node_modules:/app/frontend/node_modules
- ./frontend/:/app/frontend/
depends_on: depends_on:
db: db:
condition: service_healthy condition: service_healthy
volumes: volumes:
node_modules: {} node_modules: {}
frontend_node_modules: {}

View File

@ -6,8 +6,8 @@ services:
context: ./frontend context: ./frontend
target: develop target: develop
volumes: volumes:
- frontend_node_modules:/app/node_modules - frontend_node_modules:/app/frontend/node_modules
- ./frontend/src:/app/src - ./frontend/:/app/frontend/
labels: labels:
- "traefik.http.routers.app.rule=Host(`app.docker.localhost`)" - "traefik.http.routers.app.rule=Host(`app.docker.localhost`)"
reverse-proxy: reverse-proxy:

View File

@ -1,5 +1,5 @@
FROM node:22-alpine AS base FROM node:22-alpine AS base
WORKDIR /app WORKDIR /app/frontend
COPY package.json yarn.lock ./ COPY package.json yarn.lock ./
RUN yarn install RUN yarn install
COPY . . COPY . .
@ -12,5 +12,5 @@ EXPOSE 5173
ENTRYPOINT [ "yarn", "dev", "--host", "0.0.0.0" ] ENTRYPOINT [ "yarn", "dev", "--host", "0.0.0.0" ]
FROM nginx:alpine AS production FROM nginx:alpine AS production
COPY --from=build /app/dist/ /usr/share/nginx/html COPY --from=build /app/frontend/dist/ /usr/share/nginx/html
ENTRYPOINT [ "nginx", "-g", "daemon off;" ] ENTRYPOINT [ "nginx", "-g", "daemon off;" ]

View File

@ -18,21 +18,6 @@
filter: drop-shadow(0 0 2em #61dafbaa); filter: drop-shadow(0 0 2em #61dafbaa);
} }
@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}
.card { .card {
padding: 2em; padding: 2em;
} }

View File

@ -1,7 +1,6 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import reactLogo from './assets/react.svg' import reactLogo from './assets/react.svg'
import dockerLogo from './assets/docker.svg' import dockerLogo from './assets/docker.svg'
import viteLogo from '/vite.svg'
import './App.css' import './App.css'
function App() { function App() {
@ -38,9 +37,6 @@ function App() {
return ( return (
<> <>
<div> <div>
<a href="https://vite.dev" target="_blank" rel="noreferrer">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank" rel="noreferrer"> <a href="https://react.dev" target="_blank" rel="noreferrer">
<img src={reactLogo} className="logo react" alt="React logo" /> <img src={reactLogo} className="logo react" alt="React logo" />
</a> </a>
@ -49,7 +45,7 @@ function App() {
</a> </a>
</div> </div>
<h1>Vite + React + Docker + Traefik</h1> <h1>React + Docker + Traefik</h1>
<table> <table>
<thead> <thead>

View File

@ -33,6 +33,7 @@ Mike Conrad - SCS 2025
<p><a href="https://hackanooga.com/scs">https://hackanooga.com/scs</a></p> <p><a href="https://hackanooga.com/scs">https://hackanooga.com/scs</a></p>
<small>Includes slide deck, and repo with examples</small> <small>Includes slide deck, and repo with examples</small>
<img src="./images/talk.jpg" width="200"> <img src="./images/talk.jpg" width="200">
Connect with me on LinkedIn: https://linkedin.com/enxoco
</div> </div>
<div class="abs-br m-6 text-xl"> <div class="abs-br m-6 text-xl">