Amazon Web Services
Prerequisites: AWS account!
IMPORTANT! Dupa terminarea modulului Cloud Computing, asigurati-va ca stergeti toate resursele AWS create pentru a evita costuri suplimentare. Puteti de asemenea sa stergeti detaliile de billing (ceea ce probabil va duce la suspendarea contului, ceea ce va doriti avand in vedere ca tot ce vom porni este de test)
Amazon Web Services este unul dintre ce mai mari furnizori de servicii in Cloud. Insumeaza acum peste 200 de servicii.
Unul dintre cele mai utilizate servicii este EC2 (Elastic Compute Cloud) care pune la dispozitie masini virtuale. Scopul nostru este de a porni o astfel de masina virtuala, a ne conecta la ea si a face disponibila aplicatia creata in pasii anteriori catre internet.
1. Lansare masina virtuala
Din pagina principala, accesam EC2 (search -> type EC2)

Asigurati-va ca sunteti in regiunea eu-central-1 (Frankfurt)
Dupa ce va asigurati ca sunteti in regiunea corecta, apasati Launch an instance

Denumiti instanta de masina virtuala cum doriti
Alegeti Ubuntu. 22.04. Instance type - t2.micro

Key pair (login) - Create a new key pair. Denumiti-o cum doriti -> save. Se va salva automat. Nu o pierdeti

Network settings - allow all

Launch si asteptam sa porneasca instanta
Puteti vedea instanta apasand pe Instances in meniul din stanga

2. Atasarea unui Elastic IP
AWS atribuie o adresa IP unica instantelor create. Aceasta este realocata altei instante in momentul in care inchidem instanta noastra, iar la repornire va primi alta. Acest comportament poate duce la confuzie si erori neprevazute. Pentru a ne asigura ca masina noastra virtuala are o adresa constanta, ii vom atribui o adresa IP Elastica (Elastic IP).
Din meniul din stanga, click Elastic IPs -> Allocate Elastic IP address

All default, click Allocate
Inapoi in Dashboard-ul Elastic IPs, selectati adresa nou creata -> Actions -> Associate Elastic IP address (sau apasati pe bannerul verde care ar trebui sa apara deasupra paginii)

Alegeti instanta nou creata, click Associate

In Dashboard-ul Instances veti vedea in dreptul instantei create, pe coloana Elastic IP (probabil va trebui sa scrolati), adresa IP Elastica asociata
Acum ne putem conecta la instanta nou creata
3. Conectarea la instanta EC2
Identificati adresa IP a instantei create (Elastic IP). Vom avea nevoie de ea pentru a ne conecta la instanta
In folderul in care ati salvat cheia, deschideti un terminal (eu folosesc git bash)
Rulati comanda: (-i indica faptul ca ne conectam utilizand o cheie (identity_file))
ssh -i <cheia>.<extensia> ubuntu@<adresa_ip>
exemplu:
ssh -i cloud-computing.pem ubuntu@4.18.2.77
Probabi veti fi intrebati daca doriti sa salvati adresa IP in known_hosts. Type yes.
We're in!
4. Configurarea instantei EC2
Folosind consola instantei create in pasul anterior...
4.1. Actualizam pachetele din instanta
Run sudo apt update
Run sudo apt upgrade
4.2. Instalam Nginx
Run sudo apt install nginx
Run sudo service nginx start
Accessing the server from a browser now shows a "Welcome to nginx!" message
4.3. Modificam configurarea Nginx
Run sudo nano /etc/nginx/sites-available/default pentru a accesa fisierul de configurare nginx
Stergeti tot ce este in fisier si copiati urmatorul cod. Astfel vom indica faptul ca ne dorim ca serverul nostru sa afiseze aplicatia care va rula pe portul 3000 (dupa ce o vom deschide)
// /etc/nginx/sites-available/default
server {
location / {
proxy_pass http://localhost:3000/;
}
}
Ctrl + S ca sa salvati
Ctrl + X ca sa iesiti din fisier
Run sudo service nginx reload pentru a incarca fisierul de configurare modificat
Accesand acum adresa serverului, vom primi mesajul de eroare 502. Este in regula
4.4. Instalam Docker
Run sudo apt install apt-transport-https ca-certificates curl software-properties-common
Run curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
Run echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Run sudo apt update
Run apt-cache policy docker-ce
Run sudo apt install docker-ce
Run sudo systemctl status docker
Output should look like this now:

Ctrl + C to exit
4.5. Enable Docker usage without sudo
Inainte de a asigura acces sudo pentru comenzile docker, va trebui sa adaugam o parola pentru userul ubuntu (creat de AWS la pornirea instantei EC2)
Run sudo su -
Run passwd ubuntu
Setati o parola (si notati-o intr-un fisier local / nu o pierdeti)
Ne intoarcem la userul ubuntu. Run: su -l ubuntu
Acum putem asigura acces sudo pentru comenzile docker
Run sudo usermod -aG docker ${USER}
Run su - ${USER}
Introduceti parola pe care ati setat-o la pasul precedent
Done!
Pentru a testa ca totul a mers conform planului, rulati docker images
Output should look like this:

4.6. Pregatim proiectul pentru a fi introdus intr-o imagine Docker
Modificam fisierul next.config.js pentru a indica faptul ca pregatim proiectul pentru a fi trimis in productie. Inseram linia output: "standalone"
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
output: "standalone",
}
module.exports = nextConfig
In root-ul proiectului NextJS din calculatorul personal, vom crea fisierul Dockerfile (atentie, denumirea trebuie sa fie exact Dockerfile) cu urmatorul continut (copy paste - documentatia oficiala Vercel)
FROM node:18-alpine AS base
# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
else echo "Lockfile not found." && exit 1; \
fi
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
# ENV NEXT_TELEMETRY_DISABLED 1
RUN yarn build
# If using npm comment out above and use below instead
# RUN npm run build
# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
# Uncomment the following line in case you want to disable telemetry during runtime.
# ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
In root-ul proiectului NextJS, vom crea fisierul .dockerignore (atentie, denumirea trebuie sa fie exact Dockerfile) cu urmatorul continut (copy paste - documentatia oficiala Vercel)
Dockerfile
.dockerignore
node_modules
npm-debug.log
README.md
.next
.git
Salvam si trimitem in repository-ul remote modificarile pentru ca le vom accesa din instanta noastra EC2 (git add . , git commit -m "Docker init" , git push origin [numele branch-ului] in terminal)
4.7. Aducem proiectul in instanta noastra
Inapoi in consola instantei EC2 configurate vom aduce proiectul NextJS cu ajutorul Git. Pentru aceasta avem nevoie de link-ul de clonare al repository-ului nostru. Il gasiti in GitHub - clone (am trecut prin acest proces aici)
Clonam repository-ul - git clone [link_repo] (un folder cu numele repository-ul va fi creat automat)
Run ls pentru a vedea continutul folderului curent. Ar trebui sa vedeti numele folderului care contine repository-ul
Run cd [nume_repo] pentru a accesa folderul
Adaugam fisierul .env:
Run touch .env
Run sudo nano .env
Copiati continutul fisierului .env de pe calculatorul vostru in fisierul .env creat in instanta
Ctrl + S to save
Ctrl + X to exit
Run docker build -t nextjs-docker . (Atentie, este un punct (.) dupa numele imaginii, nu il uitati)
Asteptam
Daca rulam docker images vom vedea imaginea nou creata
Pornim un proces utilizand imaginea creata. Run docker run -d --restart always -p 3000:3000 nextjs-docker
Daca accesam adresa instantei, vom vedea aplicatia noastra!
Last updated