Cours Vibe coding avec l'IA · Module 13: Clone de Twitch

Docker & conteneurs

1 min de lecture
Dans cette leçon2

Conteneuriser une application Next.js.

Dockerfile

1FROM node:20-alpine AS base
2
3FROM base AS deps
4WORKDIR /app
5COPY package*.json ./
6RUN npm ci
7
8FROM base AS builder
9WORKDIR /app
10COPY --from=deps /app/node_modules ./node_modules
11COPY . .
12RUN npm run build
13
14FROM base AS runner
15WORKDIR /app
16ENV NODE_ENV=production
17COPY --from=builder /app/.next/standalone ./
18COPY --from=builder /app/.next/static ./.next/static
19COPY --from=builder /app/public ./public
20
21EXPOSE 3000
22CMD ["node", "server.js"]

Docker Compose

1version: '3.8'
2services:
3  app:
4    build: .
5    ports:
6      - "3000:3000"
7    environment:
8      - DATABASE_URL=postgresql://...

À bientôt !

Code de cette leçon : App.tsx
1'use client';
2
3interface StreamCardProps {
4  title: string;
5  category: string;
6  viewerCount: number;
7  channelName: string;
8  thumbnail: string;
9}
10
11const mockStreams: StreamCardProps[] = [
12  {
13    title: 'On code un bateau pirate à partir de zéro !',
14    category: 'Software & Game Development',
15    viewerCount: 1247,
16    channelName: 'Capitaine Barbe-Rouge',
17    thumbnail: 'https://images.unsplash.com/photo-1544551763-46a013bb70d5?w=400&h=225&fit=crop'
18  },
19  {
20    title: 'Tuto JavaScript - Créer des applis React',
21    category: 'Software & Game Development',
22    viewerCount: 892,
23    channelName: 'Matelot Sam',
24    thumbnail: 'https://images.unsplash.com/photo-1517694712202-14dd9538aa97?w=400&h=225&fit=crop'
25  },
26  {
27    title: 'Patterns avancés en TypeScript',
28    category: 'Science & Technology',
29    viewerCount: 567,
30    channelName: 'Navigatrice Nancy',
31    thumbnail: 'https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=400&h=225&fit=crop'
32  }
33];
34
35function StreamCard({ stream }: { stream: StreamCardProps }) {
36  return (
37    <div className="bg-gray-900 rounded overflow-hidden hover:scale-105 transition cursor-pointer">
38      <div className="relative">
39        <img
40          src={stream.thumbnail}
41          alt={stream.title}
42          className="w-full aspect-video object-cover"
43        />
44        <div className="absolute top-2 left-2 px-2 py-1 bg-red-600 text-white text-xs font-bold rounded">
45          LIVE
46        </div>
47        <div className="absolute bottom-2 left-2 px-2 py-1 bg-black/70 text-white text-xs rounded">
48          {stream.viewerCount.toLocaleString()} viewers
49        </div>
50      </div>
51
52      <div className="p-3">
53        <h3 className="font-semibold mb-1 line-clamp-2">{stream.title}</h3>
54        <p className="text-sm text-gray-400 mb-1">{stream.channelName}</p>
55        <p className="text-xs text-gray-500">{stream.category}</p>
56      </div>
57    </div>
58  );
59}
60
61export default function StreamGrid() {
62  return (
63    <div className="min-h-screen bg-gray-950 text-white p-8">
64      <h1 className="text-3xl font-bold mb-6">Live Channels</h1>
65
66      <div className="grid grid-cols-3 gap-4">
67        {mockStreams.map((stream, i) => (
68          <StreamCard key={i} stream={stream} />
69        ))}
70      </div>
71    </div>
72  );
73}

Tu as repéré une erreur dans cette leçon ?

Teste tes connaissances

Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.

  1. 1. Pourquoi conteneurise-t-on une application Next.js avec Docker ?

  2. 2. Quelle image de base le Dockerfile de la leçon utilise-t-il ?

Tâches pratiques dans le jeu

  • Tri vertical

    Ordonne les étapes du Dockerfile depuis le début du fichier :

  • Tri horizontal

    Ordonne le mapping de port dans docker-compose (une ligne) : "3000:3000"

Articles utiles