본문 바로가기

공부기록/42 Seoul

[ft_services] nginx 설정

subject PDF 내 nginx 컨테이너에 대한 요구사항

nginx 서버 컨테이너는 80번 포트와 443번 포트를 listening 합니다. http로 연결되는 80번 포트로 접근할 경우, https 인 443번 포트로 301 리다이렉션 되게 해야합니다. 페이지는 http 오류만 아니라면 어떻게 보이든 상관없습니다. 

이 컨테이너는 /wordpress 경로로 접근하면 IP:WPPORT 로 307 리다이렉트 되어야합니다.
/phpmyadmin 경로로 접근하면 reverse proxy 를 이용해 IP:PMAPORT 로 접근할 수 있어야합니다.

* WPPORT : WordPress 포트
* PMAPORT : PhpMyAdmin 포트
nginx 컨테이너에 SSH 로그인을 통해 접근할 수 있게 만드세요.

 

/wordpress 와 /phpmyadmin 으로 연결해주는 것은, 아직 wp와 pma 컨테이너를 만들지 않았으니 나중에 하기로 하고 나머지 요구사항만 먼저 만들어보기로 했다. SSH 를 빼면 ft_server에서 만들었던 nginx 서버와 크게 다르지 않다.

 

nginx 컨테이너 만들기

Dockerfile을 먼저 작성한 후 컨테이너에 접속해서 ft_server 복습의 시간을 가졌다. 생각보다 그 때 대충 넘어갔던 것들이 많았다.

FROM alpine:3.12.0

# install required packages
RUN apk update \
	&& apk --update --no-cache add \
	nginx \
	openssl \
	openssh-server

COPY ./nginx_setup.sh /usr/sbin/nginx_setup.sh
RUN chmod +x /usr/sbin/nginx_setup.sh
COPY ./default.conf /etc/nginx/conf.d/

EXPOSE 80 443 22

ENTRYPOINT ["/usr/sbin/nginx_setup.sh"]
  • --update : 최신버전으로
  • --no-cache : 로컬에 패키지의 인덱스를 저장하지 않는다. Docker 컨테이너를 가볍게 유지할 수 있다. 
  • openssh-server : openssh 는 openssh-server와 openssh-client를 포함한다. 여기서 openssh-server 만 설치하는 이유는 우리 과제에선 client를 쓸 일이 없기 때문이고, 가벼운 컨테이너를 지향하는 alpine linux 를 쓰는 목적에 맞춰 컨테이너를 더 가볍게 유지하기 위함이다.

RUN, CMD, ENTRYPOINT 에 대하여

  • 도커파일에서 RUN 명령은 실행할 때 마다 레이어가 생성되고 캐시된다. 각각의 레이어마다 달라진 점이 commit 되면서 쌓이는 형태로 컨테이너가 빌드되기 때문에, cd 명령 같은걸 RUN으로 실행하면 달라진 점이 없는 셈이라 명령이 먹히지 않고 넘어간다. ㅠㅠ
  • 그러므로 && 으로 명령들을 연결해서 하나의 RUN 으로 실행하거나, 파일로 컨테이너 내에서 실행할 명령들을 쉘 스크립트에 담아서 내부에서 실행해줘도 된다. 난 후자 선택
  • ENTRYPOINT 는 docker run 해줄 때 실행되는 명령이라고 보면 된다. 자세한건 아래 링크 참고
 

[Docker] RUN vs CMD vs ENTRYPOINT in Dockerfile

[Docker] RUN vs CMD vs ENTRYPOINT in Dockerfile by 스뎅(thDeng) on January 8, 2017 헷갈리기 쉬운 Docker Dockerfile 명령어, RUN, CMD, ENTRYPOINT. 모두 뭔가 실행하는 명령어이다. RUN. 새로운 레이어에서 명령어를 실행하고

blog.leocat.kr

 

  • default.conf 작성은 ft_server랑 거의 똑같아서 설명생략

nginx_setup.sh

컨테이너 내부에서 실행될 쉘 파일

#!/bin/sh

# ssl configuration
mkdir -p /etc/nginx/ssl
openssl req -new -x509 -nodes -newkey rsa:4096 -keyout localhost-nginx.key -out localhost-nginx.crt -days 365 -subj "/C=KR/ST=Seoul/L=Seoul/O=42Seoul/CN=localhost"
mv localhost-nginx.key /etc/nginx/ssl
mv localhost-nginx.crt /etc/nginx/ssl

# 모든 프로토콜에 대해 호스트 키 생성
ssh-keygen -A
# SSH로 접속할 수 있는 유저 생성
# 비밀번호로 접속하는 것을 막고 ssh key로만 접속할 수 있게함.
adduser --disabled-password ${SSH_USERNAME}
echo "${SSH_USERNAME}:${SSH_PASSWORD}" | chpasswd

mkdir -p /run/nginx
echo "<h1>THIS IS hjung's FT_SERVICES NGINX INDEX.HTML</h1>" >> /var/www/index.html

/usr/sbin/sshd
/usr/sbin/nginx -g "daemon off;"

nginx_setup.sh

  • nginx를 구동할 때 /run/nginx/ 디렉토리가 있어야 nginx.pid 파일이 정상적으로 생성되어 nginx 구동이 가능. 없으면 오류남.
  • index.html 파일 간단하게 생성.
    • minikube에 서비스 후 브라우저에서 external-IP로 접속하면 이 페이지가 보이는 걸 확인하기 위해 간단하게 생성
  • ssh 설정
    • SSH는 외부에서 접속해서 서버를 만져야하는 경우가 생길 수 있기 때문에 필요하다. 서버에서 요청해서 컨텐츠를 받는 거 말고, 서버 자체에 접속할 수 있게 하기 위함이다.
    • SSH 로그인 정보는 민감한 정보가 될 수 있으므로 secret 으로 따로 빼서 설정해봤다.
    • secret을 사용하는 자세한 방법은 조금 후에.
  • daemon off 에 대하여
    • docker container의 경우 daemon off; 는 nginx를 foreground에서 실행하도록 한다. 한 컨테이너에 하나의 서비스만 존재할 때 사용함.
    • -g 는 그냥 global 옵션.

 

도커 자주 쓰는 명령어 정리

👇

더보기
#dockerfile로 image 생성
docker build . -t [이미지 이름]

#image 기반 container 생성
docker run -it -p 80:80 -p 443:443 [이미지 이름]

#컨테이너에 접속
docker exec -it [컨테이너 이름] /bin/bash

#컨테이너 삭제
docker rm [컨테이너 id]

#이미지 삭제
docker rmi [이미지 id]

#이미지 지우면서 컨테이너도 같이 삭제하려면 -f 옵션
docker rmi -f [이미지 id]

 


이제 잘 만든 nginx 컨테이너를 minikube에 올려보자.

nginx.yaml

Service

  • IP 고정하기
# metallb로 하여금 서비스들의 ip를 모두 똑같게 설정하게 함
metallb.universe.tf/allow-shared-ip: "shared"
# 그 IP 주소를 정확하게 지정할 수 있음
loadBalancerIP : 192.168.99.100 
  • 포트는 TCP를 이용하되, 서비스는 80 포트로 서비스를 하고(port: 80), 서비스의 80 포트의 요청을 컨테이너의 80 포트로 연결(targetport: 80)해서 서비스를 제공한다.
ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80

 

Secret 사용법

nginx-secret.yaml 로 파일을 분리해준다.

SSH 로그인 아이디는 user, 비밀번호는 pass 로 설정했다.

apiVersion: v1
kind: Secret
metadata:
  name: ssh-secret
stringData:
  username: user
  password: pass

nginx-secret.yaml

 

Deployment 내에서 아래와 같이 참조

env:
- name: SSH_USERNAME
    valueFrom:
      secretKeyRef:
        name: ssh-secret
        key: username
- name: SSH_PASSWORD
    valueFrom:
      secretKeyRef:
        name: ssh-secret
        key: password

nginx.yaml

 

 

이제 minikube에 apply 해주면 kubectl get svc 에서 External IP 주소를 확인할 수 있다.


결과

브라우저에서 External IP 로 접근하니 nginx 서버 내 index.html 파일이 잘 보인다.

ssh 로그인 확인방법

터미널에서 이렇게 하면 비밀번호 입력하라고 나오고 무사히 접속됨. 

$ ssh user@192.168.99.100

하지만

  • 접속 종료 후 컨테이너를 종료 시켰다가 다시 띄우면, WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! 가 뜨면서 안됨
  • ~/.ssh/known_hosts 에 등록된 정보와 달라졌기 때문에 뜨는 오류로, 해당 ip의 정보를 지워야 함
  • ssh-keygen -R 192.168.99.100 하면 지워지고 다시 접속하면 잘 접속됨

  

trivia 

 

nginx 코드 참고

github.com/hysimok/ft_services/tree/main/srcs/nginx