DevOps-1: Dokeruj swoją aplikację Golang z bazą danych PostgreSQL.
W tym artykule postaramy się zadokować prostą aplikację golang CRUD z bazą danych PostgreSQL. Najpierw stwórzmy naszą aplikację.
Warunek wstępny:
- Musisz zainstalować język programowania go na swoim komputerze.
- Musisz zainstalować silnik dokera na swoim komputerze.
- Dobrze mieć trochę wiedzy programistycznej.
devops (katalog)
├── main.go
Teraz zacznijmy od napisania prostego programu w go, który wyświetli „Witaj, świecie!” aby lepiej zrozumieć, jak uruchomić program go. Umieść kod w pliku main.go.
package main
import "fmt"
func main() {
fmt.Println("Hello World!")
}
Po prostu otwórz terminal w tym samym katalogu, w którym znajduje się plik main.go , napisz go run main.go i naciśnij enter. Tada! Powinieneś zobaczyć „Hello World” w terminalu. Jeśli nie, sprawdź, czy go jest naprawdę zainstalowane na twoim komputerze, czy nie. Dane wyjściowe powinny wyglądać tak…
─mahin@dev$ go run main.go
Hello World!
package main
import (
"encoding/json"
"log"
"net/http"
"github.com/gorilla/mux"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/postgres"
)
type User struct {
gorm.Model
Name string `json:"name"`
Email string `json:"email"`
}
var db *gorm.DB
func main() {
var err error
db, err = gorm.Open("postgres", "host=localhost user=admin dbname=go-app sslmode=disable password=secret")
if err != nil {
log.Fatal(err)
}
defer db.Close()
db.AutoMigrate(&User{})
router := mux.NewRouter()
router.HandleFunc("/users", getUsers).Methods("GET")
router.HandleFunc("/users/{id}", getUser).Methods("GET")
router.HandleFunc("/users", createUser).Methods("POST")
router.HandleFunc("/users/{id}", updateUser).Methods("PUT")
router.HandleFunc("/users/{id}", deleteUser).Methods("DELETE")
log.Println("Application running")
log.Fatal(http.ListenAndServe(":8000", router))
}
func getUsers(w http.ResponseWriter, r *http.Request) {
var users []User
db.Find(&users)
json.NewEncoder(w).Encode(users)
}
func getUser(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
var user User
db.First(&user, params["id"])
json.NewEncoder(w).Encode(user)
}
func createUser(w http.ResponseWriter, r *http.Request) {
var user User
json.NewDecoder(r.Body).Decode(&user)
db.Create(&user)
json.NewEncoder(w).Encode(user)
}
func updateUser(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
var user User
db.First(&user, params["id"])
json.NewDecoder(r.Body).Decode(&user)
db.Save(&user)
json.NewEncoder(w).Encode(user)
}
func deleteUser(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
var user User
db.First(&user, params["id"])
db.Delete(&user)
json.NewEncoder(w).Encode("User deleted")
}
Uruchom go uruchom main.go
Co! Znowu błędy!
Tak! To bardzo oczywiste, ponieważ używamy niektórych pakietów z zewnątrz. Więc najpierw musimy mieć te pakiety na naszej maszynie. W tym celu musisz wykonać poniższe polecenia w terminalu.
$ go mod init devops
$ go mod tidy
$ go mod vendor
$ go run main.go
Zacznijmy od zrozumienia, czym jest serwer? Serwer to nic innego jak komputer podłączony do internetu, na którym wdrażamy (uruchamiamy) nasz program.
Nie rozumiem?
Jeśli możemy uruchomić powyższy kod aplikacji na naszej maszynie, to ujawni port 8080 dla żądań API, ale jest to ważne tylko dla hosta lokalnego, ponieważ nasza maszyna nie jest bezpośrednio połączona z Internetem, dlatego nikt z zewnątrz nie będzie mógł uzyskać dostępu punkty końcowe.
Ale! Jeśli możemy uruchomić kod aplikacji w taki sam sposób, jak zrobiliśmy to na naszej maszynie na serwerze, to możesz powiedzieć, że wdrożyłeś aplikację i każdy z dowolnego miejsca na świecie może uzyskać dostęp do twoich punktów końcowych API za pomocą ip serwera i portu. Rozumiem?
Więc, co robi tutaj docker?
Widzisz, nie możemy uruchomić aplikacji, ponieważ baza danych PostgreSQL nie jest zainstalowana na naszym komputerze. Aplikację możemy uruchomić po zainstalowaniu bazy danych, ale instalacja bazy zajmie więcej pamięci i czasu. Mogą się też zdarzyć błędy.
Może się zdarzyć inna sytuacja, na przykład obecnie używasz PostgreSQL w wersji 9. Po kilku dniach będziesz musiał używać wersji 12 dla bazy danych, co wtedy zrobisz? Musisz ponownie zainstalować nową wersję z wieloma trudnościami.
Jeśli możemy rozwiązać wszystkie te trudności, pisząc tylko kilka linii kodu, który będzie bezpieczny, łatwy, przenośny i skalowalny w tym samym czasie, czy nie będzie to dobra decyzja? Tak! doker to robi.
Nie instalujmy ręcznie bazy danych PostgreSQL, zamiast tego użyjmy jednego z najlepszych narzędzi do konteneryzacji, jakim jest docker.
Krok 3: Utwórz nowy plik o nazwie docker-compose.yaml w katalogu.
devops
├── docker.compose.yaml
├── go.mod
├── go.sum
├── main.go
└── sprzedawca
Po prostu nie martw się o inne pliki i katalogi po wykonaniu polecenia go mod init i vendor. Do tej pory stworzyliśmy tutaj tylko 2 pliki, main.go i docker-compose.yaml
Teraz zapiszemy konfigurację PostgreSQL w pliku docker-compose.yaml .
version: '3'
services:
db:
image: postgres:13-alpine
restart: always
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: secret
POSTGRES_DB: go-app
Na razie po prostu otwórz terminal i wpisz docker compose up i naciśnij enter. Powinieneś zobaczyć coś takiego…
$ docker compose up
[+] Running 3/9
⠦ db Pulling 13.7s
⠿ f56be85fc22e Pull complete 2.2s
⠿ 256414453fba Pull complete 2.4s
⠿ f71699d7795a Pull complete 2.6s
⠋ 874ea11cefcd Waiting 7.1s
⠋ ef8405c7a1c0 Waiting 7.1s
⠋ 625d593f2852 Waiting 7.1s
⠋ c4ba7b4e694b Waiting 7.1s
⠋ 17f71bede1cd Waiting 7.1s
devops-db-1 | 2023-05-03 17:56:14.394 UTC [36] LOG: database system is shut down
devops-db-1 | done
devops-db-1 | server stopped
devops-db-1 |
devops-db-1 | PostgreSQL init process complete; ready for start up.
devops-db-1 |
devops-db-1 | 2023-05-03 17:56:14.572 UTC [1] LOG: starting PostgreSQL 13.10 on x86_64-pc-linux-musl, compiled by gcc (Alpine 12.2.1_git20220924-r4) 12.2.1 20220924, 64-bit
devops-db-1 | 2023-05-03 17:56:14.572 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
devops-db-1 | 2023-05-03 17:56:14.572 UTC [1] LOG: listening on IPv6 address "::", port 5432
devops-db-1 | 2023-05-03 17:56:14.604 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
devops-db-1 | 2023-05-03 17:56:14.648 UTC [51] LOG: database system was shut down at 2023-05-03 17:56:14 UTC
devops-db-1 | 2023-05-03 17:56:14.677 UTC [1] LOG: database system is ready to accept connections
Spróbujmy teraz ponownie uruchomić naszą aplikację. Proszę nie zamykać terminala, w którym działa baza danych. Otwórz nowy terminal w tym samym katalogu i napisz go run main.go i naciśnij enter.
Wciąż pojawiają się te same błędy, prawda? Dlaczego tak?
Ponieważ jesteśmy bardzo blisko zrozumienia koncepcji dockera.
Co to jest kontener dokera?
Jest to lekki, wykonywalny pakiet oprogramowania, który zawiera wszystko, co jest potrzebne do uruchomienia aplikacji. Kontener Dockera jest odizolowany od siebie (jeden kontener do drugiego) i hosta.
Przeczytaj wiersz ponownie. jest odizolowany od komputera hosta. Dlaczego? Tworzy wirtualną sieć. Na razie powiedzmy, że sieć wirtualna to inny komputer, na którym kontener obsługuje bazę danych postgreSQL i nie możemy połączyć się z bazą danych, ponieważ nie znamy adresu IP tej maszyny/kontenera. Skąd wiemy, że działa w innej sieci?
Możesz uzyskać adres IP, uruchamiając poniższe polecenie w terminalu.
$ docker container inspect container_id
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2fa09a0ae0ee postgres:13-alpine "docker-entrypoint.s…" 36 minutes ago Up 36 minutes 5432/tcp devops-db-1
Jak w takim razie możemy uzyskać dostęp do bazy danych z naszego komputera hosta? Musimy go zmapować. Zatrzymaj uruchomiony terminal kontenera i edytuj plik tworzenia dokera:
version: '3'
services:
db:
image: postgres:13-alpine
restart: always
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: secret
POSTGRES_DB: go-app
ports:
- "5432:5432"
Teraz ponownie uruchom polecenie docker-compose i poczekaj, aż uruchomi się i będzie gotowe do zaakceptowania połączenia.
$ docker compose up
[+] Running 1/0
⠿ Container devops-db-1 Created 0.0s
Attaching to devops-db-1
devops-db-1 |
devops-db-1 | PostgreSQL Database directory appears to contain a database; Skipping initialization
devops-db-1 |
devops-db-1 | 2023-05-03 18:39:01.127 UTC [1] LOG: starting PostgreSQL 13.10 on x86_64-pc-linux-musl, compiled by gcc (Alpine 12.2.1_git20220924-r4) 12.2.1 20220924, 64-bit
devops-db-1 | 2023-05-03 18:39:01.127 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
devops-db-1 | 2023-05-03 18:39:01.127 UTC [1] LOG: listening on IPv6 address "::", port 5432
devops-db-1 | 2023-05-03 18:39:01.144 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
devops-db-1 | 2023-05-03 18:39:01.165 UTC [22] LOG: database system was shut down at 2023-05-03 18:37:20 UTC
devops-db-1 | 2023-05-03 18:39:01.179 UTC [1] LOG: database system is ready to accept connections
╭─mahin@dev in ~/dev/github.com/go/devops on master ✘
╰$ docker compose up
[+] Running 1/1
⠿ Container devops-db-1 Recreated 0.3s
Attaching to devops-db-1
devops-db-1 |
devops-db-1 | PostgreSQL Database directory appears to contain a database; Skipping initialization
devops-db-1 |
devops-db-1 | 2023-05-03 18:42:47.790 UTC [1] LOG: starting PostgreSQL 13.10 on x86_64-pc-linux-musl, compiled by gcc (Alpine 12.2.1_git20220924-r4) 12.2.1 20220924, 64-bit
devops-db-1 | 2023-05-03 18:42:47.790 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
devops-db-1 | 2023-05-03 18:42:47.790 UTC [1] LOG: listening on IPv6 address "::", port 5432
devops-db-1 | 2023-05-03 18:42:47.816 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
devops-db-1 | 2023-05-03 18:42:47.850 UTC [22] LOG: database system was shut down at 2023-05-03 18:42:09 UTC
devops-db-1 | 2023-05-03 18:42:47.868 UTC [1] LOG: database system is ready to accept connections
$ go run main.go
2023/05/04 00:47:27 Application running
W kolejnej części postaramy się zrozumieć koncepcję obrazu dockera oraz stworzymy obraz dla serwera go.
Następna część jest tutaj .
Dziękuję za przeczytanie mojego artykułu.