私はドッカーを使って2つのコンテナをまとめてドッキングすることができます。なぜ私の2つのコンテナが互いに通信できないのか分かりません。DockerアプリケーションコンテナはMySQLコンテナと通信しません
私のアプリのための私のdockerfileは次のとおりです。
FROM golang
ADD . /go/src
WORKDIR /go/src
RUN go get github.com/go-sql-driver/mysql
RUN go get github.com/gorilla/mux
RUN go build -o bin/main main.go app.go model.go
ENTRYPOINT /go/src/bin/main
EXPOSE 8080
と私のドッキングウィンドウ-compose.ymlが
version: '3'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
ports:
- "3306:3306"
expose:
- "3306"
environment:
MYSQL_ROOT_PASSWORD: testrootpassword
MYSQL_DATABASE: testing
MYSQL_USER: testuser
MYSQL_PASSWORD: testpassword
api:
depends_on:
- db
build: .
ports:
- "8080:8080"
# restart: always
environment:
APP_DB_HOST: db:3306
APP_DB_NAME: testing
APP_DB_USERNAME: testuser
APP_DB_PASSWORD: testpassword
volumes:
db_data:
メインアプリはちょうど確立するために、ポート8080でサーバーを起動し、試行ですSQLへの接続。完全な実装はここにある:私は、アプリケーションの罰金を構築するドッキングウィンドウコマンドdocker-compose up -d --build
を使用していたアプリケーションを実行するにはhttps://github.com/bliitzkrieg/go-sql-testing
package main
import (
"os"
)
func main() {
a := App{}
a.Initialize(
os.Getenv("APP_DB_USERNAME"),
os.Getenv("APP_DB_PASSWORD"),
os.Getenv("APP_DB_NAME"))
a.Run(":8080")
}
app.go
package main
import (
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
"strconv"
_ "github.com/go-sql-driver/mysql"
"github.com/gorilla/mux"
)
type App struct {
Router *mux.Router
DB *sql.DB
}
func (a *App) Initialize(user, password, dbname string) {
connectionString :=
fmt.Sprintf("%s:%[email protected]/%s", user, password, dbname)
var err error
a.DB, err = sql.Open("mysql", connectionString)
if err != nil {
log.Fatal(err)
}
a.ensureTableExists()
a.Router = mux.NewRouter()
a.initializeRoutes()
}
func (a *App) ensureTableExists() {
if _, err := a.DB.Exec(tableCreationQuery); err != nil {
log.Fatal(err)
}
}
func (a *App) Run(addr string) {
log.Fatal(http.ListenAndServe(":8080", a.Router))
}
func (a *App) initializeRoutes() {
a.Router.HandleFunc("/", a.sayHello).Methods("GET")
a.Router.HandleFunc("/products", a.getProducts).Methods("GET")
a.Router.HandleFunc("/product", a.createProduct).Methods("POST")
a.Router.HandleFunc("/product/{id:[0-9]+}", a.getProduct).Methods("GET")
a.Router.HandleFunc("/product/{id:[0-9]+}", a.updateProduct).Methods("PUT")
a.Router.HandleFunc("/product/{id:[0-9]+}", a.deleteProduct).Methods("DELETE")
}
func (a *App) sayHello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello Luca!")
}
func (a *App) getProduct(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, err := strconv.Atoi(vars["id"])
if err != nil {
respondWithError(w, http.StatusBadRequest, "Invalid product ID")
return
}
p := product{ID: id}
if err := p.getProduct(a.DB); err != nil {
switch err {
case sql.ErrNoRows:
respondWithError(w, http.StatusNotFound, "Product not found")
default:
respondWithError(w, http.StatusInternalServerError, err.Error())
}
return
}
respondWithJSON(w, http.StatusOK, p)
}
func (a *App) getProducts(w http.ResponseWriter, r *http.Request) {
products, err := getProducts(a.DB)
if err != nil {
respondWithError(w, http.StatusInternalServerError, err.Error())
return
}
respondWithJSON(w, http.StatusOK, products)
}
func (a *App) createProduct(w http.ResponseWriter, r *http.Request) {
var p product
decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&p); err != nil {
respondWithError(w, http.StatusBadRequest, "Invalid request payload")
return
}
defer r.Body.Close()
if err := p.createProduct(a.DB); err != nil {
respondWithError(w, http.StatusInternalServerError, err.Error())
return
}
respondWithJSON(w, http.StatusCreated, p)
}
func (a *App) updateProduct(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, err := strconv.Atoi(vars["id"])
if err != nil {
respondWithError(w, http.StatusBadRequest, "Invalid product ID")
return
}
var p product
decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&p); err != nil {
respondWithError(w, http.StatusBadRequest, "Invalid resquest payload")
return
}
defer r.Body.Close()
p.ID = id
if err := p.updateProduct(a.DB); err != nil {
respondWithError(w, http.StatusInternalServerError, err.Error())
return
}
respondWithJSON(w, http.StatusOK, p)
}
func (a *App) deleteProduct(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, err := strconv.Atoi(vars["id"])
if err != nil {
respondWithError(w, http.StatusBadRequest, "Invalid Product ID")
return
}
p := product{ID: id}
if err := p.deleteProduct(a.DB); err != nil {
respondWithError(w, http.StatusInternalServerError, err.Error())
return
}
respondWithJSON(w, http.StatusOK, map[string]string{"result": "success"})
}
func respondWithError(w http.ResponseWriter, code int, message string) {
respondWithJSON(w, code, map[string]string{"error": message})
}
func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) {
response, _ := json.Marshal(payload)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
w.Write(response)
}
const tableCreationQuery = `CREATE TABLE IF NOT EXISTS products
(
id SERIAL,
name TEXT NOT NULL,
price NUMERIC(10,2) NOT NULL DEFAULT 0.00,
CONSTRAINT products_pkey PRIMARY KEY (id)
)`
。 docker ps
を実行すると、SQL Serverが起動していることがわかり、apiコンテナのログを見ると、1行で2017/10/01 06:54:14 dial tcp 127.0.0.1:3306: getsockopt: connection refused
と表示されます。ハードコードされた接続文字列を使ってアプリケーションをローカルに実行したところ、正常に動作しました。私は本当に何が起こっているか分からないので、うまくいけば誰かが私を助けることができます!
乾杯!
のために彼はまた、そうでない場合は、コンテナがドッカーネットワーク上の名前 'db'と使用できなくなり、コンテナに名前' db'を与える必要があります。 'container_name:db'です。 – blacklabelops
@maybeg、デフォルトでは、作成ネットワーク内でサービス名を検出できます。だからあなたは 'container_name:db'を必要としません。彼のサービス名はすでに' db'なので、これはまったく必要ではありません。そのような場合には、コンテナ名を変更するのではなく、ネットワークエイリアスを使用する方が良い方法もあります。 –
ありがとうございました!それによって私の設定も改善されます! – blacklabelops