diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..87059b4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +# Stage 1: build +FROM node:20-alpine AS build +WORKDIR /app +COPY package*.json ./ +RUN npm install +COPY . . +RUN npm run build # Esto genera /dist + +# Stage 2: serve con Nginx +FROM nginx:alpine +COPY --from=build /app/dist /usr/share/nginx/html +COPY nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..505ddf1 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,86 @@ +pipeline { + agent any + + environment { + APP_NAME = "pablotj-portfolio-web" + IMAGE_NAME = "${APP_NAME}" + REGISTRY_URL = "registry.pablotj.com" + NAMESPACE = "andromeda" + USER = "andromeda" + PASS = credentials('docker-registry-password') + TAG = "latest" + HOST_PORT = "8080" + CONTAINER_PORT = "3000" + IMAGE_FULL = "${REGISTRY_URL}/${NAMESPACE}/${IMAGE_NAME}:${TAG}" + } + + stages { + stage('Prepare Workspace & Checkout') { + steps { + echo "Cleaning workspace" + deleteDir() + } + } + + + stage('Checkout') { + steps { + echo "Checking out repo..." + checkout scm + } + } + + stage('Load Environment') { + steps { + echo "Loading .env secret from Jenkins..." + withCredentials([file(credentialsId: 'pablotj-portfolio-website-env', variable: 'SECRET_ENV')]) { + sh 'cp $SECRET_ENV .env' + } + } + } + + stage('Build Docker Image') { + steps { + echo "Building Docker image..." + sh ''' + docker build -t ${IMAGE_NAME}:${TAG} . + ''' + } + } + + stage('Tag & Push Docker Image') { + steps { + echo "Tagging and pushing Docker image to registry..." + sh ''' + docker tag ${IMAGE_NAME}:${TAG} ${IMAGE_FULL} + echo $PASS | docker login ${REGISTRY_URL} -u ${USER} --password-stdin + docker push ${IMAGE_FULL} + ''' + } + } + + stage('Deploy Docker Container') { + steps { + echo "Stopping old container and running new container..." + sh ''' + docker stop ${APP_NAME} || true + docker rm ${APP_NAME} || true + docker run -d \ + --name ${APP_NAME} \ + -p ${HOST_PORT}:${CONTAINER_PORT} \ + --env-file .env \ + ${IMAGE_FULL} + ''' + } + } + } + + post { + success { + echo "✅ Deployment completed successfully!" + } + failure { + echo "❌ Pipeline failed!" + } + } +} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0bb245c --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +APP_NAME=pablotj-portfolio-web +IMAGE_NAME=$(APP_NAME) + +REGISTRY_URL=registry.pablotj.com +NAMESPACE=andromeda +TAG?=latest + +HOST_PORT=8080 +CONTAINER_PORT=3000 + +IMAGE_FULL=$(REGISTRY_URL)/$(NAMESPACE)/$(IMAGE_NAME):$(TAG) + +build: + docker build -t $(IMAGE_NAME):$(TAG) . + +tag: + docker tag $(IMAGE_NAME):$(TAG) $(IMAGE_FULL) + +push: + docker push $(IMAGE_FULL) + +run: + docker run -d \ + --name $(APP_NAME) \ + -p $(HOST_PORT):$(CONTAINER_PORT) \ + --env-file .env \ + $(IMAGE_FULL) + +stop: + docker stop $(APP_NAME) || true + docker rm $(APP_NAME) || true + +deploy: build tag push stop run \ No newline at end of file