데이터베이스에 로컬로 연결된 API를 개발하고 테스트하는 것은 농담이 아닙니다. 데이터베이스는 종종 문제점이 됩니다. 그러나 Docker를 사용하면 프로세스가 더 쉽고 간단해져서 복제가 쉬워집니다. 이 블로그에서는 MySQL 데이터베이스를 사용하여 Golang API를 Dockerize하고 Docker Compose를 준비하는 방법을 살펴보겠습니다.
데모를 위해 RESTful Golang API를 만들었습니다. MySQL 데이터베이스에 대한 일정 생성, 삭제, 편집과 같은 CRUD 작업을 수행할 수 있습니다. 프로젝트 README에서 엔드포인트, 메서드 등에 대해 자세히 알아볼 수 있습니다. 우리의 주요 목표는 Dockerization 부분에 초점을 맞추는 것이기 때문에 API 작동 방식에 너무 깊이 들어가지는 않을 것입니다.
앱을 Dockerzing하려면 Dockerfile을 만들어야 합니다. Dockerfile을 작성하는 방법에는 100가지가 있으며 잘못된 것도 없고 옳은 것도 없습니다. 모든 개인/회사에는 고유한 관행과 작성 방식이 있습니다. 우리의 경우 Dockerfile의 네 가지 모범 사례를 따라 더 작고 더 안전한 더 좋고 최적화된 이미지를 얻을 것입니다. Dockerfile 작성을 시작하기 전에 4가지 방법을 모두 이해하고 이를 구현하는 이유를 살펴보겠습니다.
더 밝은 기본 이미지 사용: 거의 모든 언어에 대해 더 밝은 버전의 이미지가 있습니다. 가벼워진다는 것은 몇 메가바이트 더 작다는 의미가 아니라 10배 더 작을 수 있다는 의미입니다. 더 가벼워진 이유는 더 작고 더 안전하게 만드는 불필요한 종속성을 포함하지 않기 때문입니다. 예, 종속성이 높아지면 보안 위험도 높아집니다. 노드, Golang 등을 위한 불스아이 및 알파인 버전이 있을 것입니다.
다단계 빌드: Docker의 강력한 기능 중 하나이며 빌드 단계를 병렬로 실행할 수 있고 필요한 파일과 항목을 복사하여 최종 이미지를 생성할 수도 있습니다. 다른 단계에서 프로그램을 실행하는 데 필요한 항목만 갖고 있습니다.
바이너리 만들기: 많은 언어에서는 소스 코드에서 바이너리 만들기를 지원하므로 전체 소스 코드를 처리할 필요가 없기 때문에 바이너리를 작고 실행하기가 훨씬 쉽습니다. 또한 언어장벽에 관계없이 어떠한 환경에서도 뛸 수 있습니다.
레이어 분할: 우리가 알고 있듯이 Dockerfile의 모든 명령은 레이어이며, 레이어를 분할하는 것은 빌드 속도를 높이는 좋은 방법입니다. 예를 들어 소스에서 모든 파일(설치할 종속성 파일과 함께)을 복사한 다음 종속성을 설치하는 경우 종속성을 변경하지 않았더라도 이미지를 다시 빌드할 때마다 모든 파일을 복사하고 종속성을 설치합니다. 이를 극복하기 위해 여러 계층으로 나누고 한 단계로 종속성 파일을 복사하여 설치할 수 있습니다. 다음 단계에서는 모든 파일을 복사할 수 있습니다. 이제 코드를 변경하고 이번에 다시 빌드하면 모든 파일을 복사하는 레이어만 다시 빌드되고 종속성 단계는 그대로 유지됩니다(변경 사항이 없으므로 캐시됨). 아래 Dockerfile에서도 예제를 볼 수 있습니다. 우리는 기본 이미지, 종속성 등과 같이 변경이 적은 단계가 위에서 아래로 접근하는 방식으로 Dockerfile을 작성합니다.
여기 Go API용으로 만든 Dockerfile이 있습니다.
# Build Stage FROM golang:alpine3.20 AS builder WORKDIR /build COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go build -o /app . # Final Stage FROM alpine:3.20 COPY --from=builder /app /app CMD ["/app"]
FROM에서 본격적인 golang을 사용하고 단계 빌더 이름을 지정하는 대신 golang:alpine 버전을 기본 이미지로 사용했음을 알 수 있습니다. 이름/레이블은 한 단계에서 다음 단계로 파일을 복사하는 데 도움이 됩니다. 또 다른. 그런 다음 작업 디렉터리를 만들었습니다. 그런 다음 모든 파일을 함께 복사하는 대신 go.mod 및 go.sum을 복사하고 종속성을 설치했습니다(위의 레이어 분석 지점에서 그 이유를 설명했습니다).
이제 종속성이 설치되면 나머지 파일을 복사합니다. 그런 다음 go build를 실행하고 -o 출력 플래그를 사용하여 바이너리 이름을 현재 위치로 지정하여 소스 코드에서 바이너리를 생성합니다.
이제 흥미로운 점은 마지막 단계에서는 golang 이미지 등이 필요하지 않으며 이제 바이너리가 있으므로 Alpine 기본 이미지를 사용할 수 있고 프로그래밍에 관계없이 모든 Linux 시스템에서 실행할 수 있다는 것입니다. 언어 특성. 다음 단계에서는 빌더 단계에서 최종 단계까지 바이너리를 복사해서 실행해보겠습니다.
그렇습니다. 이것이 우리 앱을 Dockerzie하는 방법이며 사용자 생성 및 루트가 아닌 사용자로 실행 등과 같은 모범 사례를 도입하여 Dockerfile을 더욱 개선할 수 있습니다. 이제 Dockerfile을 사용하여 이미지를 빌드하고 실행한 다음 원격 또는 필요한 자격 증명을 제공한 다음 해당 API 엔드포인트를 사용하여 로컬 MySQL 서버에 액세스합니다.
But, we will not stop here we will take a step further, and we will also run a MySQL server in a container and connect with our app. But, one point to note here is we can run a spin of a MySQL container and connect our API container to that, but there is so much manual work and long commands to type in the terminal, and things can go wrong. To overcome this we will use Docker Compose instead to make our life easier.
Let's create a file called compose.yml and use the blow config.
services: app: container_name: go-api build: context: . dockerfile: Dockerfile image: go-api ports: - 8080:8080 environment: - DB_HOST=mysql - DB_PORT=3306 - DB_USER=user - DB_PASSWORD=password - DB_NAME=my-database depends_on: mysql: condition: service_healthy networks: - go-network mysql: container_name: go-mysql image: mysql:9.0 environment: - MYSQL_ROOT_PASSWORD=password - MYSQL_USER=user - MYSQL_PASSWORD=password volumes: - dbdata:/var/lib/mysql networks: - go-network healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s timeout: 5s retries: 3 volumes: dbdata: networks: go-network: driver: bridge
It's a pretty basic configuration, but a couple of key things I want to mention is that if we see DB_HOST is mysql, there is no localhost or ip because in compose services communicate with other services by the service name. This is out-of-the-box networking provided by Docker Compose.
Another point, it often happens when working with Docker Compose where we have two services: an app and a database, and the app service starts first and crashes because the database isn't ready when the app tries to connect. To overcome this, we set up a healthcheck for the database to confirm its readiness. Then, in our app service, we can use depends_on with a condition to ensure the app only starts when the database service is healthy.
Now when we do Docker compose for 1st time, we might encounter an error saying permission denied because it doesn't have permission as well as a database with the name my_database, so we need to both by execing into the container.
Even though our app has crashed the DB is still up and running. We can check by doing docker ps.
Now exec into the container by doing docker exec -it
mysql -u root -p
It will ask for the password, enter the password you mentioned in the compose.yml file. Once we log in, we can create a database. Create a database with the same name specified in the compose file. In my case, it's my_database. Execute the below command:
CREATE DATABASE my_database;
Now to give the right privileges and flush it execute the below command.
GRANT ALL PRIVILEGES ON my_database.* TO 'user'@'%'; FLUSH PRIVILEGES;
Once we are done, we need to stop the running compose service and restart again by doing docker compose up
That's it for this blog. I'm glad you're still reading and made it to the end—thank you so much for your support and reading. I sometimes share tips on Golang on Twitter. You can connect with me there.
위 내용은 MySQL을 사용하여 Golang API를 Dockerizing하고 Docker Compose 지원을 추가합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!