목적

PHP + MySQL 웹 게시판(도커 패키지화 상태)을 각종 Google Cloud 서비스를 통해 배포


1. 주요 코드 점검 및 수정

디렉터리 구조

본 코드들은 로컬 환경에서 작동하기에 문제없는 코드지만, 클라우드 환경에서는 문제 발생
이유는 각 환경에 차이점이 존재하기 때문

차이점

Local 환경
docker-compose.yml 사용
MySQL + PHP를 묶어서 관리
쉬운 데이터베이스 접근
Cloud 환경
독립 단일 컨테이너 Cloud Run을 통해 실행
독립 단일 데이터베이스 Cloud SQL에서 인스턴스 제공
이 둘을 연결하기 위해 Cloud SQL Auth Proxy 연결 방식 사용

즉, 로컬 환경에 맞춰 제작된 코드를 클라우드 환경에 맞게 수정할 예정

Cloud SQL Auth Proxy
애플리케이션의 Cloud SQL 데이터베이스 접근을 돕는 도구 및 프록시
데이터베이스 접속 정보 제공 or 환경 변수 설정 방법 존재
gcloud의 IAM 권한 확인, 보안 경로 생성, Unix 소켓을 통한 데이터베이스 연결 과정
Unix 소켓
같은 시스템 속 프로세스 간 통신 파일
프록시가 생성한 경로 속 해당 소켓을 통해서만 통신 가능


db.php

//수정 전
<?php

$host = 'db';
$user = 'scpuser';
$pw = 'scppass';
$dbname = 'scp';

$conn = new mysqli($host, $user, $pw, $dbname);

if ($conn->connect_error) {
	die('MySQL 연결 실패' . $conn->connect_error);
}

?>

                                                      
                                                      
//수정 후
<?php

//Cloud Run에 입력 및 설정할 환경변수
//데이터베이스 연결 정보 호출 용도
//getenv() : 실행되는 서버의 환경 변수 값을 읽어오는 함수(PHP 내장 함수)
//getenv() 사용 이유 : Cloud Run은 컨테이너에 직접 접근할 수 없기때문 + 민감 정보들 하드코딩 방지
$db_socket = getenv('DB_SOCKET_PATH');  //Cloud Run -> Cloud SQL 접근 Unix 소켓 경로
$db_name = getenv('DB_NAME');
$db_user = getenv('DB_USER');  
$db_password = getenv('DB_PASSWORD');

//Cloud SQL Auth Proxy를 통해 Unix 소켓 연결
//new mysqli() 인자값 : (첫 null - 호스트명 / Unix 소켓에는 호스트명 불필요, 두번째 null - 포트번호 / Unix 소켓을 사용하기에 포트 불필요)
$conn = new mysqli(null, $db_user, $db_password, $db_name, null, $db_socket);

if ($conn->connect_error) {
    die("데이터베이스 연결 실패: " . $conn->connect_error);
}

?>

 

Dockerfile

FROM php:8.2-apache

RUN docker-php-ext-install mysqli

RUN mkdir -p /var/www/html/uploads && chmod 777 /var/www/html/uploads

COPY . /var/www/html/

RUN a2enmod rewrite

EXPOSE 80



FROM php:8.2-apache

#Composer 설치
#COPY : 파일 복사 명령어
# --from=composer : 해당 이름을 가진 이미지에서 파일을 가져오는 옵션
#lastest : 이미지 이름
#/usr/bin/composer : 이미지 내부의 composer 실행 위치 및 경로
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

RUN docker-php-ext-install mysqli

#zip 확장 모듈 설치
#RUN : Dockerfile 컨테이너 내부 셸 실행 명령어
#apt-get update : 패키지 목록 업데이트 명렁어
#apt-get install -y libzip-dev : libzip(개발 라이브러리)설치 명령어 
#docker-php-ext-install zip : zip 확장 모듈 설치 및 라이브러리 모듈 빌드 활성화
RUN apt-get update && apt-get install -y libzip-dev \
    && docker-php-ext-install zip

#composer.json : 라이브러리 목록 및 버전 정의 파일
#composer.lock : composer 설치시 자동 생성되는 파일 / 모든 환경 호환 목적
COPY composer.json composer.lock ./

#composer install : 모든 패키지 설치 명령어
#--no-dev : 개발에만 쓰이는 등 불필요한 파일 제거 옵션
#--optimize-autoloader : Composer 오버로딩 최적화
RUN composer install --no-dev --optimize-autoloader

RUN mkdir -p /var/www/html/uploads && chmod 777 /var/www/html/uploads

COPY . /var/www/html/

RUN a2enmod rewrite

#CMD : 컨테이너 실행 명령어 정의
#apache2ctl : Apache 서버 제어 스크립트
#-D : Define / Apache 서버 특정 정의 전달 옵션
#FOREGROUND : Apache 프로세스 유지 및 컨테이너 실행 유지 모드
#-k start : Apache 서버 시작 명령어
#-c : Configuration / 명령 및 추가 설정 지정 옵션
#Listen ${PORT} : Apache 서버에서 외부 요청 수신 포트 번호 지정
#${PORT} 사용 이유 : Cloud Run에서 사용할 포트 번호를 환경 변수를 통해 동적으로 할당하기 위해
CMD ["apache2ctl", "-D", "FOREGROUND", "-k", "start", "-c", "Listen ${PORT}"]

Composer
라이브러리 및 패키지 관리자


2. 필요 API 활성화

프로젝트 ID : round-device-468004-p1

Google Cloud는 감사하게 무료 체험판 3개월 이용 가능

GCP 콘솔 검색창에서 "API 및 서비스" 검색

각 주요 API들이 활성화되어 있는지 확인 필요
활성화되어있지 않다면,
"+ API 및 서비스 사용 설정"  → "API 및 서비스 검색" 직접 활성화

Cloud Rum Admin API

Docker 이미지 기반 컨테이너 배포 및 관리가 목적인 API
이를 활성화해야 GCP가 Cloud Run 서비스 생성, 수정, 삭제 등 모든 작업 수행 가능

Cloud SQL Admin API

Cloud SQL 인스턴스 관리가 목적인 API
이를 활성화해야 Cloud SQL 인스턴스 생성, Cloud Run 서비스와의 연결 및 고급설정 가능

Artifact Registry API

Docker 이미지나 패키지 저장 및 관리가 목적인 API
이를 활성화해야 로컬에서 빌드한 이미지를 GCP 저장소에 업로드 가능
만약 비활성화 시 Cloud Run에서 저장소 속 이미지를 가져오는 것은 불가능


3. 인스턴스 + 데이터베이스 생성

인스턴스
클라우드 환경에서 실행되는 하나의 독립적인 데이터베이스 서버를 의미
해당 서버는 GCP에서 관리해 주므로, 따로 운영체제 관리나 보안 패치가 불필요

인스턴스 생성 이유
웹 애플리케이션이 데이터를 저장하고 읽을 수 있는 데이터베이스 서버 생성 목적
로컬 MySQL을 더 이상 사용하지 않기 때문 + 클라우드에서 안전하게 실행되기 때문
그냥 성능, 안정성, 네트워크 속도면에서 Better than anything

GCP 콘솔 검색창에서 "SQL" 검색

 "+ 인스턴스 만들기"  -> "MySQL 선택" -> Cloud SQL 버전 선택(Enterprise plus / Enterprise)

데이터베이스 버전, 인스턴스 ID, (루트)비밀번호, 리전 선택

리전
GCP은 전 세계 여러 곳에 분산되어 있는 데이터 센터 보유
즉, 서버실이 위치하고 있는 지역을 의미
가까운 지역의 센터가 최적화된 성능 제공
애플리케이션(Cloud Run)과 데이터베이스(Cloud SQL)가 서로 통신하기 때문
만약 동일한 리전을 고르지 않아, 멀리 떨어져 있으면 네트워크 지연, 추가 비용 발생

인스턴스 생성 완료


SQL 페이지 왼쪽메뉴 "데이터베이스" -> "+데이터베이스 만들기"

데이터베이스 이름 입력 및 나머지는 기본값

 

"scp" 데이터베이스 생성


4. 계정 권한 확인 

GCP 콘솔 검색창에서 "IAM 및 관리자" 검색

주 구성원 목록 중 "Default account" 에게 역할 추가

Cloud SQL 클라이언트, 환경 및 Storage 객체 관리자 필수 선택

Cloud Run 서비스가 GCP 속 다른 서비스에 접근 및 조작을 허용하기 위해 권한 부여를 하는 것이 당연

Cloud SQL Client
Cloud SQL 인스턴스에 연결이나, 데이터를 읽고 쓸 수 있는 권한 제공
Cloud Run 컨테이너가 해당 인스턴스에 접속하여 데이터를 저장 및 조회해야 하기 때문
Cloud SQL Auth Proxy를 통해 이루어지는 핵심 권한
권한 상실 시 db.php로부터 연결 실패 발생

환경 및 Storage 객체 관리자
Cloud Composer 환경 및 Cloud Storage 객체 관리 권한
버킷 업로드 및 관리

Default account 필요 역할 부여


5. 버킷 설정 및 테이블 연결

GCP 콘솔 검색창에서 "Cloud Storage" 검색

Cloud Storage 왼쪽메뉴 "버킷" -> "+만들기"

스토리지
저장소

GCP에서는 저장 서비스는 전부 스토리지라고 통칭 (ex. Cloud Filestore, Cloud SQL 등)

버킷
스토리지 내에 있는 데이터를 담은 최상위 컨테이너
즉, 가장 먼저 만들어져야 하는 폴더를 의미
모든 파일은 반드시 버킷에 저장
파일 관리 / 권한 설정 / 데이터 수명 주기 관리

전역적으로 고유한 이름 입력

 

위 단계에서 계속 선택했던 리전 동일 선택

 

제작한 버킷에 sql 파일 업로드

Cloud SQL에 데이터베이스.sql 파일을 직접 업로드하는 기능은 없는 것으로 인지 
Cloud Storage를 경유하는 방식 채택

애초에 로컬환경에서 제작된 sql파일을 직접 연결하는 것보다
안전하고, 빠르고,
외부 접속을 계속 열지 않기에 보안적이고,
대용량 파일 처리도 효율적이고,
... etc 

SQL 페이지 내 "인스턴스" → 상단의 "가져오기"

Storage에 버킷이 문제없이 생성되고, 파일 업로드도 기깔나게 되었다면 문제없이 파일 선택 가능
이외에 파일 형식, 대상 위치 확인


6. 레지스트리 생성 및 Docker 이미지 빌드/푸시

GCP 콘솔 검색창에서 "Artifact Registry" 검색


레지스트리
컨테이너 이미지 저장 및 관리 서비스 전체를 의미
쉽게 로컬에서 만든 Docker 이미지를 옮길 저장소라고 생각
결국 Cloud Run을 위해 필요
version tag를 통해 특정 버전별 이미지 배포 가능
이미지 보안 용이

이름, 형식, 리전 설정 및 나머지는 기본값

 

레지스트리 생성

 

 

gcloud CLI 설치  |  Google Cloud SDK Documentation

이 페이지는 Cloud Translation API를 통해 번역되었습니다. 의견 보내기 gcloud CLI 설치 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 이 페이지에는 Google Cloud CLI

cloud.google.com

Google Cloud CLI
Google Cloud Platform을 제어하는 명령 도구 모음
GCP, Artifact Registry 인증 및 연결
서비스 관리

 

Docker Desktop: The #1 Containerization Tool for Developers | Docker

Docker Desktop is collaborative containerization software for developers. Get started and download Docker Desktop today on Mac, Windows, or Linux.

www.docker.com

Docker Desktop
Docker 컨테이너를 로컬환경에서 제작/실행하도록 하는 애플리케이션
최종 배포될 컨테이너 이미지를 만드는(docker build) 역할
Artifact Registry 등 저장소에 업로드(docker push) 역할
로컬에서 오류 검증 및 테스트  

로컬환경 + GCP 연결 및 초기 설정

gcloud init

gcloud init 입력
사용 계정, 프로젝트명 선택
해당 리전 선택 (list 명령어 사용 가능)
완료

 

gcloud + Docker 연결 설정

gcloud auth configure-docker asia-northeast3-docker.pkg.dev

<asia-northeast3> : 사용자의 리전
gcloud auth : 인증 관련 명령어
configure-docker : docker 명령어의 인증 처리 방식 "설정"
docker.pkg.dev : 리전에 해당하는 이미지 저장소에 대한 인증 "설정"

Docker에서 GCP의 저장소로 이미지를 올리기 위한 별도의 과정


해당 명령어의 초기 결과값

Credential helper for asia-northeast3-docker.pkg.dev configured to use gcloud.

config.json 파일 업데이트 메세지
Docker가 Artifact Registry에 인증이 완료되었다는 의미

안타깝게 이미 인증 상태

credHelpers : Docker 인증과 인증 도우미 사용 정의 "설정"

해당 로그는 이미 인증 도우미 설정과 함께 config.json파일이 있다는 의미


Docker 이미지 빌드 및 패키징 with Dockerfile

docker build -t my-php-app:latest .

<my-php-app> : Artifact Registry에서 확인 가능한 이미지의 고유 이름
docker build : Docker 이미지 빌드 지시 명령어
-t : 태그 지정 옵션
latest : 이미지 버전 태그
. : 현재 작업 중인 디렉터리를 의미

어떤 환경에서는 빌드하여 이미지 생성 및 문제 방지

Docker Desktop 미실행

실행 오류

Docker를 꼭 ON하고 진행할 것

[internal] load : Dockerfile을 읽고, 빌드하여 Docker 엔진으로 전송하는 과정
CACHED [stage-0 ~] : 실행 과정이 이미 이전에 성공하여 캐시에 저장되었다는 의미

잠깐만!! 빌드 이전에 composer.json 작성 필수

composer.json 작성

require : 필수 작성 및 의존성 목록 정의
google/cloud-storage : 사용 라이브러리 이름 및 피접근자
^1.30 : 라이브러리 버전 조건

빌드 이후

composer.lock
모든 라이브러리의 버전 및 해시값 기록
즉, 모두 같은 버전의 라이브러리 사용 가능
Cloud Run 환경은 라이브러리 버전이 중요

이미지 경로(Arifact Registry)로 태그 지정

docker tag my-php-app:latest asia-northeast3-docker.pkg.dev/round-device-468004-p1/scp/my-php-app:latest

<my-php-app> : Artifact Registry에서 확인 가능한 이미지의 고유 이름
<asia-northeast3> : 사용자의 리전
<round-device-468004-p1> : 사용자의 프로젝트 ID

scp : 사용자의 Artifact Registry명

docker tag : Docker 이미지의 태그 변경, 추가, 복사 등 실행 명령어
ex. docker tag [원본 이미지] / [새로운 (복사) 이미지]
원본 이미지를 복사하여 새로운 이미지로써 태그를 부여

이미지 Artifact Registry 푸시

docker push asia-northeast3-docker.pkg.dev/round-device-468004-p1/scp/my-php-app:latest

docker push : Docker 이미지를 Registry로 push 하는 명령어
ex. docker push [원본 도메인] / [새로운 위치]
클라우드 서비스는 로컬의 이미지를 직접 가져오지 못하기에 꼭꼭 필요한 절차

태그 지정 및 푸시

 

push 성공시 Artifact Registry 속 이미지 생성 확인


7. 배포

GCP 콘솔 검색창에서 "Cloud Run" 검색

"+ 서비스 만들기"

생성된 이미지를 올바른 경로에서 찾아 선택

 

그밖의 서비스 이름, 리전, 인증방식 선택

 

환경 변수 세팅
마지막 단계로 Cloud SQL과 연결

 

배포 완료

+ Recent posts