Прежде всего, давайте более подробно рассмотрим Dockerfile.Для этого вопроса я также настроил репозиторий для демо-целей. .
# We use a so called two stage build.
# Basically this means we build our go binary in one image
# which has the go compiler and all the required tools and libraries.
# However, since we do not need those in our production image,
# we copy the binary created into a basic alpine image
# resulting in a much smaller image for production.
# We define our image for the build environment...
FROM golang:1.11-alpine3.8 as build
# ...and copy our project directory tp the according place.
COPY . "/go/src/github.com/mwmahlberg/so-postgres-compose"
# We set our work directory...
WORKDIR /go/src/github.com/mwmahlberg/so-postgres-compose
# ...and add git, which - forever reason, is not included into the golang image.
RUN apk add git
# We set up our dependency management and make sure all dependencies outside
# the standard library are installed.
RUN set -x && \
go get github.com/golang/dep/cmd/dep && \
dep ensure -v
# Finally, we build our binary and name it accordingly
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /apiserver
# Now for the second stage, we use a basic alpine image...
FROM alpine:3.8
# ... update it...
RUN apk --no-cache upgrade
# .. and take the binary from the image we build above.
# Note the location: [/usr]{/bin:/sbin} are reserved for
# the OS's package manager. Binaries added to an OS by
# the administrator which are not part of the OS's package
# mangement system should always go below /usr/local/{bin,sbin}
COPY --from=build /apiserver /usr/local/bin/apiserver
# Last but not least, we tell docker which binary to execute.
ENTRYPOINT ["/usr/local/bin/apiserver"]
Последняя строка должна действительно выполнять трюк: ENTRYPOINT
указывает команду, которая будет выполнена, когдаКонтейнер запущен.Аргументы прилагаются к этой команде.Таким образом, чтобы добавить строку подключения, вы можете сделать следующее:
api:
build: .
restart: always
command: "host=db user=user dbname=dbname sslmode=disable password=123"
ports:
- 8080:8080
links:
- db
Последнее, что вы должны сделать, - это иметь статическую конфигурацию для образа докера, как показано в вашем примере.Вы в основном устанавливаете статическую строку соединения, которая лишает вас большей гибкости при использовании контейнеров.
Однако, imho, это плохая практика - использовать флаги командной строки для настройки контейнеров, в первую очередь.Гораздо более гибкий способ - использовать переменные окружения.Например, в kubernetes вы бы использовали карту конфигурации для настройки переменных среды, которые, в свою очередь, настраивают модуль.Однако переменные окружения также могут использоваться с docker-compose или docker swarm.
Следовательно, я бы изменил docker-compose.yml
на что-то вроде этого:
version: '3'
services:
db:
volumes:
- ./db/pgdata:/pgdata
image: postgres
ports:
- "5432"
restart: always
environment:
- POSTGRES_USER=user
- POSTGRES_DB=dbname
- POSTGRES_PASSWORD=123
- PGDATA=/pgdata
# adminer added for convenience
adminer:
image: adminer
restart: always
ports:
- 8081:8080
depends_on:
- db
api:
build: .
restart: always
ports:
- 8080:8080
depends_on:
- db
environment:
- POSTGRES_USER=user
- POSTGRES_DB=dbname
- POSTGRES_PASSWORD=123
- POSTGRES_HOST=db
- POSTGRES_PORT=5432
и использовал бы средуПеременные для настройки двоичного файла.
Я добавил простой пример использования переменных среды в Go для репозитория.Обратите внимание, что такие проекты, как https://github.com/spf13/cobra/cobra или https://gopkg.in/alecthomas/kingpin.v2, значительно упрощают работу с переменными среды, поскольку они обеспечивают автоматическое преобразование типов, возможность легко устанавливать значения по умолчанию и многое другое.
Что касается более глубоких рассуждений о том, почему использовать переменные среды, вы можете прочитать часть 3 методологии 12-факторного приложения .
hth