Docker를 사용하여 휴대용 프런트엔드 애플리케이션 구축

전단 개발자로서의 직업 생활에서 이러한 상황에 직면할 수 있습니다. 응용 프로그램을 여러 환경에 배치하기를 원합니다.이러한 환경은 기본적으로 같지만, 응용 프로그램의 각 환경에서의 행동은 약간 다를 수 있습니다.
예를 들어 임시 환경에서 실행되는 응용 프로그램은 임시 영역에서 실행되는 API 서버를 호출해야 하거나 백색 라벨 응용 프로그램은 배치된 환경에 따라 다른 브랜드를 표시해야 할 수 있습니다.
이것이 바로 환경 변수가 도움을 줄 수 있는 곳이다.환경 파일을 제공하고 응용 프로그램이 실행될 수 있는 모든 환경에 응용 프로그램을 구축할 수 있습니다.이것은 사실상 Angular CLI, Create React AppVue CLI 등 도구가 사용하는 매우 흔한 방법이다.
이것은 매우 좋은 해결 방안이지만 응용 프로그램의 복잡성이 계속 증가할 때 두 가지 단점이 있습니다.
여러 버전
CI/CD 파이핑이 이미 설정되어 있으면 구축 서버는 모든 환경에 전체 응용 프로그램을 구축해야 합니다.응용 프로그램이 복잡할수록 기다리는 시간이 길어지고 귀중한 자원과 시간을 낭비하게 된다.
휴대성이 떨어지다
구축을 복잡하게 하는 것 외에 최종 결과를 정확한 환경에 배치해야 한다.이렇게 하는 단점은 코드는 특정한 환경에서만 실행할 수 있고 다른 곳에서는 실행할 수 없다는 것이다.
위에서 언급한 문제를 해결하기 위해서, 우리는 우리의 개발 파트너가 서버에서 실행되는 응용 프로그램에 대해 하는 일에서 주의를 얻을 수 있다. 즉, 응용 프로그램이 시작될 때 이러한 환경 변수를 제공하는 것이다.이것은 말하기 쉽고 실행하기 어렵다. 왜냐하면 우리는 응용 프로그램을 정적 파일로 배치하기 때문에 서버에서 코드를 실행하지 않기 때문이다.
Docker는 이미 운송 응용 프로그램의 업계 표준이 되었기 때문에, 우리는 이곳에서 그것을 사용하여 새로운 응용 프로그램을 배치하고 동적 환경 변수를 제공할 것이다.이전에 Docker 경험이 없는 경우 read up on this topic first으로 문의하십시오.
주의: 우리는 이곳에서 새로운 응용 프로그램을 만들지만, 아래에 개술한 절차는 컴파일하든 안 하든 기존의 전단 응용 프로그램에 적용될 수 있습니다.
먼저 index.html 파일로 응용 프로그램에 간단한 템플릿 파일을 만듭니다.
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>My awesome application</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="main.js"></script>
  </body>
</html>
여기서 script 요소를 사용하여 JavaScript를 직접 로드합니다.이렇게 하는 것은 이 강좌를 가능한 한 간단하게 하기 위해서이지만, 웹 팩이나 선택한 프레임워크의 내장 CLI 도구를 사용하여 응용 프로그램을 구축할 수 있습니다.main.js 파일을 추가하고 이를 사용하여 페이지에 내용을 추가합니다.
const root = document.getElementById('root')

root.innerHTML = '<h1>Hello World!</h1>'
만약 모든 것이 순조롭다면, 너는 마땅히 "안녕하세요, 세상!"을 보아야 한다.index.html 파일을 열 때 브라우저에 표시되는 메시지입니다.

알림: 작업 디렉터리에서 npx http-server .을 실행하면 간단한 HTTP 서버를 시작하여 로컬 개발을 할 수 있습니다.
이제 응용 프로그램을 시작하고 실행했습니다. Docker 이미지에 넣어 쉽게 공유하고 배치할 수 있습니다.우선, 우리는 새로 만든 파일을 src이라는 디렉터리에 놓을 것입니다.응용 프로그램 코드를 저장합니다. 이 코드는 최종적으로 Docker 이미지에 정적 파일로 저장됩니다.응용 프로그램을 컴파일하는 경우 dist 또는 build 디렉터리일 수 있습니다.
파일을 제공하기 위해서는 HTTP 서버가 필요합니다.작업 디렉토리의 루트 디렉토리에 Dockerfile이라는 새 파일을 만들고 다음을 추가합니다.
FROM nginx:latest
RUN rm -rf /usr/share/nginx/html/*
COPY ./src/ /usr/share/nginx/html/
여기서 최신 버전의 NGINX를 서버로 사용합니다. NGINX는 기본 시작 페이지의 파일이 삭제되고 우리 프로그램의 내용으로 바뀌는 것을 보여 줍니다.현재 우리는 Dockerfile을 가지고 있으며 작업 디렉터리에서 다음 명령을 실행하여 응용 프로그램에 Docker 이미지를 구축할 수 있습니다.
docker build --tag frontend .
이렇게 하면 "frontend"라는 레이블이 있는 새 Docker 이미지가 만들어지고 Docker run 명령과 함께 실행됩니다.
docker run --detach --publish 8080:80 --name server frontend:latest
이 명령을 실행하고 http://localhost:8080으로 이동하면 이전에 보았던 것과 같은 페이지를 볼 수 있을 것입니다. 그러나 지금은 Docker를 사용하여 NGINX에서 제공합니다!
프로젝트에 기본 환경 변수를 저장하기 위해 environment.js이라는 새 파일을 만들고 src 디렉터리에 추가합니다.
const defaultEnvironment = {
  APP_TITLE: 'Hello Docker!'
}

export default defaultEnvironment
우리는 새로운 APP_TITLE 변수를 사용하여 페이지에 표시하기를 원하기 때문에 main.js을 업데이트하여 이 점을 반영합시다.
import environment from './environment.js'

...

root.innerHTML = `<h1>${environment.APP_TITLE}</h1>`
다행이네요. 이제 이 변경들이 정상적으로 작동하는지 봅시다.다음 명령을 사용하여 실행 중인 Docker 컨테이너를 중지합니다.
docker rm --force server
Docker 컨테이너를 재구성하고 실행하려면 이전 명령을 다시 실행합니다.
docker build --tag frontend .
docker run --detach --publish 8080:80 --name server frontend:latest
만약 모든 것이 순조롭다면, 우리는 지금 APP_TITLE 변수가 예상대로 표시되는 것을 보아야 한다.

네, 지금까지는 좋았어요.Docker에서 응용 프로그램이 실행 중인 별도의 환경 변수 파일이 있습니다.그러나 우리가 어디에서 용기를 운행하든지 간에 우리의 APP_TITLE 변수는 시종 같다.응용 프로그램을 실제로 이식할 수 있도록 Docker 컨테이너를 시작할 때 어떤 방법으로 응용 프로그램에 환경 변수를 제공해야 합니다.
이를 위해 서버에서 응용 프로그램의 전송 상태를 나타낼 때, 우리는 프런트엔드 프레임워크에서 index.html을 나타낼 때 스크립트 요소에 상태를 넣는 또 다른 일반적인 방법을 사용할 것이다.index.html에 다음 코드를 추가합니다.
<script id="environment" type="application/json">$FRONTEND_ENV</script>
여기에는 Docker 컨테이너가 시작될 때 JSON 데이터로 대체할 FRONTEND_ENV이라는 자리 표시자가 추가되었습니다.
참고: 개발 중에 JSON으로 컨텐트를 해석할 때 문제가 발생하지 않도록 프로덕션 빌드에 이 스크립트 요소를 조건부로 포함하는 것이 좋습니다.Dockerfile 끝에 다음 행을 추가합니다.
COPY ./startup.sh /app/startup.sh
CMD sh /app/startup.sh
Docker는 컨테이너가 시작될 때 특정 명령을 실행할 수 있도록 CMD 명령을 제공합니다.이 예에서 우리는 startup.sh 스크립트를 Docker 이미지에 복사하고 용기가 시작된 후에 직접 실행합니다.이 스크립트가 어떤 모양인지 보고 작업 디렉터리의 루트 디렉터리에 추가합니다.
#!/bin/sh
basePath=/usr/share/nginx/html
fileName=${basePath}/index.html
envsubst < ${fileName} > ${basePath}/index.env.html
mv ${basePath}/index.env.html ${fileName}
nginx -g 'daemon off;'
이 파일에는 많은 내용이 있지만 가장 중요한 줄은 envsubst 명령을 실행하는 줄입니다.GNU gettext 유틸리티에서 제공하는 이 유틸리티는 거의 모든 Linux 릴리스의 일부이기 때문에 Docker 컨테이너이기도 합니다.index.html 파일의 내용을 읽고 달러 기호를 접두사로 하는 모든 텍스트(예: FRONTEND_ENV)를 Docker 컨테이너에 제공하는 등가 환경 변수로 대체합니다.
우리는 곧 도착할 것이다. 우리의 코드가 지금까지 정상적으로 작동하는지 봅시다.Docker image의 새 버전을 만들고 환경 변수부터 시작해야 합니다.
docker rm --force server
docker build --tag frontend .
docker run --publish 8080:80 --name server --env FRONTEND_ENV='{ "APP_TITLE": "Hello Environment!" }' frontend
여기서 볼 수 있듯이 우리는 FRONTEND_ENV을 JSON 텍스트로 Docker 용기에 제공합니다.현재 http://localhost:8080의 페이지를 열고 소스 코드를 보면 다음과 같은 내용을 볼 수 있습니다.
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>My awesome application</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="main.js"></script>
    <script id="environment" type="application/json">
      { "APP_TITLE": "Hello Environment!" }
    </script>
  </body>
</html>
예상한 바와 같이, 우리의 index.html은 현재 우리의 환경 변수를 포함하고 있다.이것은 우리가 현재 Docker 이미지를 구축하기만 하면 서로 다른 환경 변수를 제공하여 모든 환경에 배치할 수 있다는 것을 의미한다.여러 번 응용 프로그램을 구축할 필요가 없습니다!
이것은 매우 좋지만, 우리는 여전히 이 JSON 데이터를 읽고 기본 환경 변수를 덮어써야 하기 때문에, environment.js에 코드를 추가하여 이 점을 실현합시다.
const defaultEnvironment = {
  APP_TITLE: 'Hello Docker!'
}

function getEnvironmentVariables() {
  const element = document.getElementById('environment')

  if (!element?.textContent) {
    return {}
  }

  try {
    return JSON.parse(element.textContent)
  } catch (error) {
    console.warn('Unable to parse environment variables.')
  }

  return {}
}

export default {
  ...defaultEnvironment,
  ...getEnvironmentVariables()
}
여기에 환경 변수를 포함하는 요소를 가져와 그 내용을 JSON으로 해석하는 새로운 함수가 있습니다.기본 환경을 내보낼 때 index.html에서 가져온 환경 변수로 덮어씁니다.
현재 이미지를 재구성하고 이전과 같은 FRONTEND_ENV 환경 변수를 사용하여 시작하면 사용자 정의 제목이 표시됩니다.


그렇습니다!이제 응용 프로그램에 사용할 수 있는 휴대용 Docker 이미지가 생겼습니다.본문에서 사용한 전체 코드를 보려면 Github에서 찾을 수 있습니다.

좋은 웹페이지 즐겨찾기