Μετάβαση στο περιεχόμενο
Όλα τα άρθρα

Εφαρμογές Go με Docker: μια φορητή, ερμητική αλυσίδα εργαλείων

από Ghazi Triki · 10 λεπτά ανάγνωσης

Δημιουργία εφαρμογών Go με Docker
Σε αυτό το άρθρο

Σταματήστε να εγκαθιστάτε τη Go στον υπολογιστή σας. Χωρίς μολυσμένο GOPATH, χωρίς «στο δικό μου μηχάνημα δουλεύει» και χωρίς καμία απόκλιση εκδόσεων. Αυτό είναι ακριβώς το μοτίβο με το οποίο ξαναγράψαμε τους πράκτορες Java για τις αναφορές BigBlueButton Learning Analytics και φτιάξαμε τον ασφαλή Piler Go Agent. Δείτε πώς μπορείτε να παραδίδετε στατικά εκτελέσιμα μόνο με το Docker.

Του Ghazi Triki, RIADVICE

Το πρόβλημα με το «απλώς εγκαταστήστε τη Go»

Όταν διαχειριζόμασταν πράκτορες γραμμένους σε Java για τις αναφορές BigBlueButton Learning Analytics, αντιμετωπίσαμε την κλασική «κόλαση των εξαρτήσεων». Η μετάβαση στη Go υποσχόταν απλότητα, αλλά μόνο αν δεν επαναλαμβάναμε τα ίδια λάθη. Χρειαζόμασταν μια διαδικασία μεταγλώττισης τόσο ερμητική όσο και τα εκτελέσιμα που παρήγαγε.

Κάθε ομάδα κάποια στιγμή πέφτει σε αυτούς τους τοίχους:

  • Απόκλιση εκδόσεων. Ο Ahmed έχει την 1.24, ο Omar την 1.26 και ο διακομιστής παραγωγής την 1.25. Μια μικρή αλλαγή στον μεταγλωττιστή σπάει τη μεταγλώττιση, αλλά μόνο για τον Ahmed.
  • Μολυσμένοι υπολογιστές. GOPATH, GOMODCACHE και καθολικές εγκαταστάσεις εργαλείων (staticcheck, gofumpt) που διαφέρουν από σταθμό εργασίας σε σταθμό εργασίας.
  • Δύσκολη ένταξη νέων μελών. Ένας νέος μηχανικός περνά την πρώτη του μέρα παλεύοντας με μεταβλητές περιβάλλοντος και αλυσίδες εργαλείων C για το cgo.

Στη RIADVICE εκτιμούμε την πειθαρχία και την τάξη. Θέλαμε μια διαδικασία μεταγλώττισης που να τις αντανακλά: καθαρή, προβλέψιμη και κοινή για όλους.

Η συνηθισμένη απάντηση είναι «χρησιμοποιήστε Docker», αλλά οι περισσότεροι οδηγοί σας δείχνουν μόνο πώς να φτιάξετε μια εικόνα container. Δεν σας δείχνουν πώς να πάρετε ένα απλό, στατικά συνδεδεμένο εκτελέσιμο στον υπολογιστή σας, δηλαδή αυτό που πραγματικά χρειάζεστε για μια υπηρεσία systemd ή για μια εγκατάσταση σε απομονωμένο δίκτυο, χωρίς να εγκαταστήσετε ποτέ τοπικά τον μεταγλωττιστή της Go.

Shell
docker run --rm -v "$(pwd):/app" -w /app golang:1.26.5-trixie \
    go build -o dist/myapp ./cmd/myapp

Η επίσημη εικόνα golang είναι ο μεταγλωττιστής. Ο πηγαίος κώδικάς σας προσαρτάται (bind mount) στο /app. Το εκτελέσιμο γράφεται στο dist/myapp στον υπολογιστή σας. Όταν η εντολή ολοκληρωθεί, το container καταστρέφεται (--rm) και ο υπολογιστής σας μένει τόσο καθαρός όσο ήταν πριν.

Εμπειρία από την πράξη: από το BigBlueButton στο Piler

Δεν πρόκειται απλώς για θεωρία. Εφαρμόσαμε αυτό το μοτίβο σε δύο κρίσιμα έργα:

  1. BigBlueButton Learning Analytics Reports: Ξαναγράψαμε βαριούς πράκτορες Java ως ελαφριά εκτελέσιμα Go. Οι μεταγλωττίσεις μέσω Docker μάς επέτρεψαν να στοχεύσουμε ακριβώς το περιβάλλον Debian των διακομιστών BBB χωρίς να χρειαζόμαστε αυτό το περιβάλλον στους φορητούς μας υπολογιστές.
  2. Piler Go Agent: Για τη λύση μας αρχειοθέτησης email φτιάξαμε έναν πράκτορα με ενισχυμένη ασφάλεια. Η διαδικασία μεταγλώττισης έπρεπε να είναι εξίσου ασφαλής με τον κώδικα. Καρφιτσώνοντας τον μεταγλωττιστή σε συγκεκριμένο SHA, εξασφαλίσαμε ότι κάθε bit του εκτελέσιμου έχει γνωστή προέλευση.

Γιατί είναι καλύτερο από την εγκατάσταση της Go

Ζήτημαgo install στον υπολογιστήdocker run golang:...
Έκδοση GoΌποια εγκαταστήσατε τελευταίαΚαρφιτσωμένη, ίδια για όλους
GOPATH / cacheΜολύνει το ~/goΕρμητικά επίπεδα container
Αλυσίδα cgoΑπαιτεί ρύθμιση στον υπολογιστήΠεριλαμβάνεται στην επίσημη εικόνα
Ταύτιση με το CI«Στο δικό μου δουλεύει»Ίδια εικόνα, ίδιο εκτελέσιμο
Makefile
BINARY := mini-api
DIST := dist

# Version metadata derived from git
VERSION    := $(shell tmp=$$(git describe --tags --always --dirty 2>/dev/null) && echo "$${tmp#v}" || echo dev)
COMMIT     := $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
BRANCH     := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null || echo unknown)
BUILD_DATE := $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
LDFLAGS := -X example.com/mini-api/internal/version.Version=$(VERSION) \
           -X example.com/mini-api/internal/version.Commit=$(COMMIT) \
           -X example.com/mini-api/internal/version.Branch=$(BRANCH) \
           -X example.com/mini-api/internal/version.BuildDate=$(BUILD_DATE)

# Pinned toolchain image
GO_IMAGE := golang:1.26.5-trixie

# Run any command inside the Go toolchain container
define run_in_docker
    docker run --rm -v "$(PWD):/app" -w /app $(GO_IMAGE)
endef

.PHONY: build test lint

build:
    @mkdir -p $(DIST)
    $(call run_in_docker) bash -c 'CGO_ENABLED=0 go build -buildvcs=false -ldflags="$(LDFLAGS)" -o $(DIST)/$(BINARY) ./cmd/$(BINARY)'
    @echo "Built $(DIST)/$(BINARY) (version $(VERSION))"

test:
    $(call run_in_docker) go test -race ./...

lint:
    $(call run_in_docker) go vet ./...

Το Makefile: η πηγή της πειθαρχίας

Χρησιμοποιούμε ένα Makefile για να κωδικοποιήσουμε τα βήματα της μεταγλώττισης. Προσέξτε ότι το GO_IMAGE είναι καρφιτσωμένο σε συγκεκριμένη έκδοση. Δεν χρησιμοποιούμε ποτέ το latest.

Οι τεχνικές λεπτομέρειες που μετράνε

1. CGO_ENABLED=0 για στατικά εκτελέσιμα

Στον πράκτορα Piler χρειαζόμασταν εκτελέσιμα που να τρέχουν σε οτιδήποτε, από ένα σύγχρονο Debian έως έναν παλαιό διακομιστή. Η απενεργοποίηση του CGO εξασφαλίζει ότι το εκτελέσιμο περιέχει όλα όσα χρειάζεται, χωρίς δυναμικές εξαρτήσεις από βιβλιοθήκες του υπολογιστή.

2. -ldflags -X για την προέλευση

Το εκτελέσιμό σας πρέπει να μπορεί να σας πει ακριβώς από πού προήλθε. Εισάγουμε το commit του git και την ημερομηνία μεταγλώττισης κατά τη σύνδεση. Αυτό ήταν ζωτικής σημασίας για την αποσφαλμάτωση των πρακτόρων BigBlueButton σε δεκάδες διαφορετικές συστοιχίες.

3. Καρφίτσωμα της εικόνας του μεταγλωττιστή

Στην κουλτούρα μας πιστεύουμε στη συνέπεια. Το καρφίτσωμα του golang:1.26.5-trixie αντί για το latest σημαίνει ότι αν ο Ahmed μεταγλωττίσει το εκτελέσιμο σήμερα και ο Omar σε έξι μήνες, το αποτέλεσμα θα είναι ταυτόσημο bit προς bit.

Συμπέρασμα

Ο μεταγλωττιστής είναι ένα εργαλείο και, όπως κάθε εργαλείο, πρέπει να μένει στη θέση του. Μεταφέροντας την αλυσίδα εργαλείων της Go στο Docker, εξαλείψαμε μια ολόκληρη κατηγορία σφαλμάτων του τύπου «σε μένα δουλεύει» και απλοποιήσαμε την ένταξη κάθε νέου μηχανικού που έρχεται στη RIADVICE.

Είτε ξαναγράφετε πράκτορες Java είτε φτιάχνετε ένα ασφαλές API για το Piler, αυτό το μοτίβο προσφέρει την πειθαρχία και την αξιοπιστία που απαιτούν τα συστήματα παραγωγής.


Ο Ghazi Triki είναι ο ιδρυτής της RIADVICE. Αναπτύσσουμε υψηλής απόδοσης, ασφαλείς ενσωματώσεις για το BigBlueButton, το Piler και άλλα συστήματα. Ας φτιάξουμε μαζί κάτι σπουδαίο.

🔗 Δείτε το golang-docker-boilerplate στο GitHub

Κοινοποιήστε αυτό το άρθρο

  • Γενική διαθεσιμότητα του ZcaleRight 1.0.0
    BigBlueButton · 6 λεπτά ανάγνωσης

    ZcaleRight 1.0.0: δέκα διακομιστές λειτουργούν τόσο εύκολα όσο ένας

    Το ZcaleRight τοποθετεί συνεδρίες BigBlueButton σε παραγωγή από το 2019. Φτάνει στην έκδοση 1.0.0 με γενική διαθεσιμότητα: και οι 69 δυνατότητες δημοσιευμένες ανοιχτά, εγχειρίδιο μέσα στο προϊόν, συμφωνία επιπέδου υπηρεσιών πίσω του και δικός του ιστότοπος.

  • Open Source · 10 λεπτά ανάγνωσης

    Κυκλοφόρησε το Sukarix 0.4.0: ουρές Redis υψηλής απόδοσης για πραγματικά pipelines υψηλού φόρτου

    Ατομική εκτέλεση Lua, εγγενής αφαίρεση διπλοτύπων, δομημένη τηλεμετρία προόδου και αυστηρή έγχυση εξαρτήσεων: πώς το Sukarix 0.4.0 προσφέρει δυνατότητες επιχειρησιακού επιπέδου χωρίς το βάρος ενός ογκώδους framework και κινεί το pipeline πραγματικού χρόνου του BigBlueButton Analytics.

  • Από επτά χρόνια σε επτά ημέρες
    Education · 5 λεπτά ανάγνωσης

    Από 7 χρόνια σε 7 ημέρες με την αυτόνομη ΤΝ (agentic AI)

    Αν έχετε δει ποτέ ένα υπολογιστικό φύλλο COCOMO II να προβλέπει 33 ημερολογιακούς μήνες για ένα έργο που η ομάδα σας παρέδωσε σε δύο sprints, γνωρίζετε ήδη το πρόβλημα: τα μοντέλα εκτίμησης βαθμονομήθηκαν για έναν κόσμο που δεν υπάρχει πια.