docker-compose로 Golang과 MySQL 연결

20007 단어 DockerMySQLgolangtech
【환경】
MacBook Air (M1, 2020)
OS: MacOS Big Sur version11.6
Docker Desktop for Mac version4.5.0
docker-compose에서 golang과 MySQL 용기를 만들고 Docker의network를 통해 MySQL을 조작합니다.
MySQL 용기의 초기화 처리에서 article 테이블을 만들고 구글에서 이 데이터를 확인할 때까지 2개의 데이터를 로그인합니다.
디렉토리 구조
go_docker
├── docker-compose.yml
├── golang
│   ├── Dockerfile
│   └── src
│       ├── article
│       │   └── article.go
│       ├── go.mod
│       ├── go.sum
│       └── main.go
└── mysql
    ├── .env
    ├── Dockerfile
    └── init
        └── create_table.sh
mysql 디렉터리에 관해서는 docker-compose로 MySQL 시작에서 만든 디렉터리와 거의 같기 때문에 그것들을 사랑한다.
docker-compose.yml
version: '3.8'

services:
  go:
    container_name: go
    build:
      context: ./golang
      dockerfile: Dockerfile
    tty: true
    ports:
      - 8080:8080
    env_file:
      - ./mysql/.env
    depends_on:
      - db
    volumes:
      - type: bind
        source: ./golang/src
        target: /go/src
    networks:
      - golang_test_network

  db:
    container_name: db
    build:
      context: ./mysql
      dockerfile: Dockerfile
    tty: true
    platform: linux/x86_64
    ports:
      - 3306:3306
    env_file:
      - ./mysql/.env
    volumes:
      - type: volume
        source: mysql_test_volume
        target: /var/lib/mysql
      - type: bind
        source: ./mysql/init
        target: /docker-entrypoint-initdb.d
    networks:
      - golang_test_network

volumes:
  mysql_test_volume:
    name: mysql_test_volume

networks:
  golang_test_network:
    external: true
  • MySQL(db 서비스)과 docker-compose로 MySQL 시작는 기본적으로 같다.
  • yml 파일의 맨 아래 golangtest_네트워크라는 Docker의 네트워크를 기술했다.
    각 서비스의 넷워크스에서 지정을 통해 서비스 이름으로 서비스 간의 통신을 할 수 있다.
    이번에 구글과 MySQL이 통신할 때 host에'db'의 서비스 이름을 지정해서 통신할 수 있습니다.
  • go 서비스의dependson 서비스 시작 순서를 설정합니다.
    여기 지정한 서비스 (db) 가 시작되면 자체 (go) 가 시작됩니다.
  • golang/Dockerfile
    FROM golang:1.17.7-alpine
    RUN apk update && apk add git
    WORKDIR /go/src
    
    CMD ["go", "run", "main.go"]
    
    기본 Image는alpine 서버의 구글입니다.git만 가져옵니다.
    작업 디렉토리, gorun main을 설정합니다.실행 고.
    main.go
    package main
    
    import (
    	"database/sql"
    	"fmt"
    	"go_docker/article"
    	"log"
    	"os"
    	"time"
    	
    	_ "github.com/go-sql-driver/mysql"
    )
    
    func open(path string, count uint) *sql.DB {
    	db, err := sql.Open("mysql", path)
    	if err != nil {
    		log.Fatal("open error:", err)
    	}
    
    	if err = db.Ping(); err != nil {
    		time.Sleep(time.Second * 2)
    		count--
    		fmt.Printf("retry... count:%v\n", count)
    		return open(path, count)
    	}
    
    	fmt.Println("db connected!!")
    	return db
    }
    
    func connectDB() *sql.DB {
    	var path string = fmt.Sprintf("%s:%s@tcp(db:3306)/%s?charset=utf8&parseTime=true",
    		os.Getenv("MYSQL_USER"), os.Getenv("MYSQL_PASSWORD"),
    		os.Getenv("MYSQL_DATABASE"))
    
    	return open(path, 100)
    }
    
    func main() {
    	db := connectDB()
    	defer db.Close()
    	article.ReadAll(db)
    }
    
    database/sql
    데이터베이스/sql은 구글로 데이터베이스에 연결할 때 사용하는 패키지입니다.
    이번 MySQL 연결은 드라이버 "github.com/go-sql-driver/mysoql"로도 가져옵니다.가방 앞에서(밑줄) 다음에는 매크로 패키지 내의 init 메서드만 실행됩니다.프로그램에서 사용하지 않습니다.
    func connectDB() *sql.DB
    main 방법의 첫 번째 줄에서 호출합니다.
    path 변수는 데이터베이스/sql에서 지정한 연결 정보입니다.
    [user 이름]: [password] @tcp ([host 이름]: [port])/데이터base 이름
    이런 형식으로 기술하다.
    docker-compose의networks를 설정했기 때문에host명은db로 연결할 수 있습니다.
    os.환경 변수를 사용할 수 있습니다.
    func open(path string, count uint) *sql.DB
    sql.Open()을 통해 데이터베이스를 연결합니다.
    첫 번째 파라미터에서 이전에 두 번째 파라미터에 설정된 데이터베이스 형식의 path를 지정합니다.
    db.Ping()을 통해db 서비스에 연결되었는지 확인하고 실패하면 count을 줄이고 오픈 방법을 시작합니다.
    article.go
    package article
    
    import (
    	"database/sql"
    	"fmt"
    	"log"
    )
    
    type Article struct {
    	id    int
    	title string
    	body  string
    }
    
    func ReadAll(db *sql.DB) {
    	var articles []Article
    	rows, err := db.Query("select * from article;")
    	if err != nil {
    		panic(err)
    	}
    	for rows.Next() {
    		article := Article{}
    		err = rows.Scan(&article.id, &article.title, &article.body)
    		if err != nil {
    			panic(err)
    		}
    		articles = append(articles, article)
    	}
    	rows.Close()
    
    	fmt.Println(articles)
    }
    
    func ReadAll(db *sql.DB)
    세 번째 줄main 방법에서 호출합니다.
    sql.패킷에서 여러 검색 결과를 얻을 때(SELECT 등)에는 Query를, 단일 데이터를 얻을 때는 QueryRow를, 데이터를 얻지 못할 때는 Exec(INSERT, CREATE, UPDAATE, DELETE 등)를 사용한다.
    이번에는article표의 모든 데이터를 얻으려면Query 방법을 사용합니다.
    시험해 보다
    그럼 제가 실제로 docker-compose를 실행해 보겠습니다.
    % docker-compose up -d
    [+] Running 3/3
     ⠿ Volume "mysql_test_volume"  Created                                                                                                                                                                          0.0s
     ⠿ Container db                Started                                                                                                                                                                          0.3s
     ⠿ Container go                Started
    
    goo 컨테이너 로그 확인해 볼게요.
    go: downloading github.com/go-sql-driver/mysql v1.6.0
    
    retry... count:99
    
    retry... count:98
    
    retry... count:97
    
    retry... count:96
    
    retry... count:95
    
    retry... count:94
    
    retry... count:93
    
    retry... count:92
    
    retry... count:91
    
    retry... count:90
    
    retry... count:89
    
    retry... count:88
    
    retry... count:87
    
    db connected!!
    
    [{1 記事1 記事1です。} {2 記事2 記事2です。}]
    
    MySQL의 시작은 많은 시간이 걸렸지만article표의 데이터를 순조롭게 얻었다.
    참고 자료
    https://sourjp.github.io/posts/go-db/
    https://qiita.com/study-toto/items/256c2d306b3c6c8f86cd

    좋은 웹페이지 즐겨찾기