# Docker Compose
## Background
We usually create a single container application such as Docker when we create an application. Previous tasks enabled us to create a single container application using Docker, but you need to learn how to make multiplex container applications. Today's lesson aims to create multiplex container applications using docker-compose.
## Task
Based on [ref](https://qiita.com/muroya2355/items/d48c384a4a82c7ed34ae), please build a multiplex container including Golang and PostgreSQL using Docker Compose. (In your feature, you can build an environment for React-Go application.)
### Step0: Install Golang
https://go.dev/doc/install
### Step1: Create golang + postgreSQL
https://qiita.com/muroya2355/items/d48c384a4a82c7ed34ae
If you don't know GOPATH, you can get GOPATH by executing the below command.
```
go env GOPATH
```
<details><summary> Answer </summary>
### Modify the golang dockerfile
If the error has been ocurred, you should replace below command.
- Error
```
executor failed running [/bin/sh -c go get github.com/lib/pq]: exit code: 2
ERROR: Service 'app' failed to build : Build failed
```
- Dockerfile
```
# Specify the base image for the go app.
FROM golang:1.15
WORKDIR /go/src/github.com/postgres-go
# Copy everything from this project into the filesystem of the container.
COPY . .
# Obtain the package needed to run code. Alternatively use GO Modules.
RUN go get -u github.com/lib/pq
WORKDIR /go/src/yuta/go
# Add the contents of the host OS . /go contents to the working directory
ADD ./go .
```
### Modify the postgreSQL dockerfile
If the error has been ocurred, you should replace below command.
- Error
```
initdb: error: invalid locale settings; check LANG and LC_* environment variables
```
- Dockerfile
```
FROM postgres:latest
ENV LC_ALL en_US.UTF-8
ENV LC_CTYPE en_US.UTF-8
RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
ENV LANG ja_JP.UTF-
# Copy the initialization sql file to the specified directory in the container
COPY ./docker/postgres/init/*.sql /docker-entrypoint-initdb.d/
```
</details>
### Step2 Build a server in the golang container
You modify /go/main.go, Dockerfile, docker-compose.yml for building a server.
First, you copy a below code and paste it in /go/main.go.(Some parts omitted.)
We can complete building a server.
The detail of explanation is described in [this](https://note.com/miso_hijiki/n/nf816bdf23430)
```
package main
import (
"database/sql"
"fmt"
"log"
"net/http"
// postgres ドライバ
_ "github.com/lib/pq"
)
// TestUser : テーブルデータ
type TestUser struct {
UserID int
Password string
}
// main 関数
func main() {
http.HandleFunc("/a", handler)
http.ListenAndServe(":8181", nil)
}
// handler 関数
func handler(w http.ResponseWriter, r *http.Request) {
// Db: データベースに接続するためのハンドラ
var Db *sql.DB
// Dbの初期化
Db, err := sql.Open("postgres", "host=postgres user=app_user password=password dbname=app_db sslmode=disable")
if err != nil {
log.Fatal(err)
}
// SQL文の構築
sql := "SELECT user_id, user_password FROM TEST_USER WHERE user_id=$1;"
// preparedstatement の生成
pstatement, err := Db.Prepare(sql)
if err != nil {
log.Fatal(err)
}
// 検索パラメータ(ユーザID)
queryID := 1
// 検索結果格納用の TestUser
var testUser TestUser
// queryID を埋め込み SQL の実行、検索結果1件の取得
err = pstatement.QueryRow(queryID).Scan(&testUser.UserID, &testUser.Password)
if err != nil {
log.Fatal(err)
}
// 検索結果の表示
fmt.Fprintf(w, testUser.Password)
}
```
But, we didn't access the server as below in local terminal.
```
% curl localhost:8181/a
curl: (7) Failed to connect to localhost port 8181: Connection refused
```
So, please consider this problem by referring to [it](https://docs.docker.com/compose/gettingstarted/#step-3-define-services-in-a-compose-file)
The task will be terminated when the following message is displayed
```
% curl localhost:8181/a
password1
```
<details><summary> Answer </summary>
- Answer(docker-compose.yml)
Add ports under services.postgres
```
services:
postgres:
ports:
- "8181:8181"
```
</details>
### Archive
<details><summary> Open Port </summary>
### Step2 Open a port in the postgreSQL container
We doesn't access the postgreSQL container because
- Answer(docker-compose.yml)
Add ports under services.postgres
```
services:
postgres:
ports:
- "5432:5432"
```
You can execute the below commands.
```
docker exec -it postgres psql -U app_user app_db
```
</details>