Jinsi ya kutumia faili nyingi katika Docker Compose
Jifunze jinsi compose.override.yaml inavyofanya kazi, mpangilio wa kuunganisha faili, na mtego wa ports unaosababisha migogoro. Pata mbinu bora za kutenganisha mazingira ya dev na prod.
Jinsi Compose inavyoshughulikia zaidi ya faili moja
Docker Compose inaweza kujenga mradi mmoja kutoka kwa faili kadhaa. Inazisoma kwa mpangilio ilizopokea na kuziunganisha kuwa modeli moja, hivyo faili inayokuja baadaye huchukua nafasi ya thamani yoyote inayokinzana. Kuna njia mbili za kufanya hivi kutoka kwenye mstari wa amri: faili ya override ambayo Compose huipakia yenyewe, na flag ya -f unayoiingiza kwa mkono. Njia ya tatu ipo ndani ya faili yenyewe, kipengele cha include, na inafanya kazi tofauti na hizo mbili.
Uunganishaji huu si uandikaji upya wa kawaida. Mappings huunganishwa kwa msingi wa key kwa key, sequences huongezewa, na seti ndogo ya fields hubadilishwa kabisa. Tofauti hiyo ndiyo chanzo cha mshangao, na orodha ya ports ndiyo inayomkwamisha karibu kila mtu.
Kila kitu hapa chini kinachukulia kuwa unatumia Compose v2, plugin ya docker compose badala ya script ya zamani ya docker-compose. Tekeleza docker compose version ili kuhakiki. Ikiwa bado hujaandika faili ya Compose, anza na mwongozo wa misingi ya Docker Compose kisha urudi hapa.
Faili ya override ambayo Compose huipakia bila kuambiwa
Endesha docker compose up bila flag yoyote ya -f na Compose itatafuta kwenye saraka ya sasa, kisha kwenye saraka mama, kwa ajili ya compose.yaml au docker-compose.yaml. Ikiwa faili ya override ipo karibu na faili ya msingi, Compose huipakia hiyo ya pili, yenyewe tu.
ls compose.yaml compose.override.yaml
docker compose up -dFaili zote mbili zikiwepo, ni sawa na kuziandika kwa mkono.
docker compose -f compose.yaml -f compose.override.yaml up -dMajina ambayo Compose huyatambua ni compose.override.yaml, compose.override.yml, na majina ya zamani ya docker-compose.override.yml na docker-compose.override.yaml. Jina lingine lolote, kwa mfano compose.dev.yaml, hupakiwa tu pale unapolitaja kwa kutumia -f.
Pindi tu unapopitisha -f moja, upakiaji wa kiotomatiki husimama. docker compose -f compose.yaml up husoma faili hiyo moja tu na kupuuza override, ambayo ndiyo sifa inayotumiwa na muundo wa dev na prod baadaye katika mwongozo huu.
Hii ina pande mbili kwenye seva. Faili ya override iliyoachwa kwenye saraka ya deploy hupakiwa na kila amri ya docker compose inayotekelezwa kutoka saraka hiyo, ikiwemo ile inayotekelezwa na cron job yako. Hivyo ndivyo stack ya production inavyoweza kuishia kufanya bind-mount ya saraka ya source ambayo haikukusudiwa kusafirishwa. Endesha docker compose config baada ya kila deploy na usome kilichotokea. Wakati deploy hiyo haisimamiwi na mtu, ukaguzi huo husaidia tu ikiwa kuna kitu kitakachoarifu kuwa mambo yameenda vibaya, ambayo ndiyo kazi ya chaneli ya push kama seva ya ntfy inayojiendesha ambayo cron job au unit ya systemd OnFailure inaweza kutuma ujumbe.
Kupanga kwa kutumia -f, na mahali ambapo njia za relative hurejelea
Compose hujenga usanidi kwa mpangilio unaotoa faili, na faili zinazofuata hubatilisha na kuongezea zile zilizotangulia. Kutoka kushoto kwenda kulia, faili ya mwisho ndiyo inayoshinda.
docker compose -f compose.yaml -f compose.prod.yaml config
docker compose -f compose.yaml -f compose.prod.yaml up -dKila amri katika mradi huo inahitaji orodha ileile ya faili. Endesha up na faili mbili na logs na faili moja, na utakuwa unazungumza na modeli tofauti iliyounganishwa, ambayo ni njia ya haraka ya kupata huduma ambayo Compose inasema haipo. Hatari huongezeka kwa stack ambayo upgrades zake huendeshwa kama amri za mara moja, kama vile hatua ya database migration katika Chatwoot support desk inayojiendesha, ambapo docker compose run inayotolewa na orodha isiyo sahihi ya faili inalenga kimyakimya modeli tofauti na ile ambayo huduma zako tayari zinatumia. Badala yake, weka orodha hiyo mara moja kwa kutumia environment variable ya COMPOSE_FILE.
export COMPOSE_FILE=compose.yaml:compose.prod.yaml
docker compose config
docker compose up -dKitenganishi ni : kwenye Linux, na COMPOSE_PATH_SEPARATOR huibadilisha. COMPOSE_FILE inaweza pia kuishi kwenye faili ya .env ya mradi, jambo linaloifanya kuwa sehemu ya checkout badala ya kuwa sehemu ya historia ya shell yako. Chochote kilichowekwa wazi kwenye mstari wa amri (command line) hushinda environment variable.
Sasa ni kanuni inayovunja bind mounts. Unapotumia faili nyingi na -f, njia zote za relative katika faili hizo zote hurejelea saraka (directory) ya faili ya kwanza, si ile ya faili inayozishikilia. Andika ./data:/var/lib/postgresql/data ndani ya deploy/prod/compose.prod.yaml na Compose bado itatafuta ./data karibu na faili ya msingi. Docker kisha hutengeneza saraka tupu kwenye njia hiyo isiyo sahihi na container huanza bila kitu ndani yake, jambo linaloonekana kama kupoteza data kumbe si hivyo. Pitisha --project-directory ili kuweka njia ya msingi wewe mwenyewe, au tumia include, ambayo hurejelea kila faili dhidi ya saraka yake yenyewe.
Jina la mradi hutoka kwenye saraka hiyo hiyo ya msingi, kwa hivyo kubadilisha faili ipi ni ya kwanza kunaweza kubadilisha jina la mradi. Mradi uliopata jina jipya unamaanisha majina mapya ya container na majina mapya ya volume, na volume ya zamani bado iko kwenye diski chini ya jina la zamani. Ibandike (pin) badala yake kwa kutumia name: ya ngazi ya juu katika faili ya msingi.
name: myappNi sehemu zipi huunganishwa, na zipi hubadilishwa
Compose huunganisha usanidi kulingana na aina ya thamani, si kwa jina la sehemu.
- Sehemu zenye thamani moja hubadilishwa.
image,command,entrypointnamem_limithuchukua thamani ya baadaye moja kwa moja. Huwezi kuongeza hoja moja kwenyecommand, kwa sababu ubatilishaji (override) huandika upya mstari mzima. - Ramani (mappings) huunganishwa kwa kila ufunguo.
environment,labels,volumesnadeviceshuhifadhi kila ufunguo kutoka kwenye faili zote mbili, na faili ya baadaye ndiyo inayoshinda kwenye ufunguo wowote uliopo katika faili zote mbili. Kwaenvironmentnalabels, ufunguo ni jina la kigezo (variable) au lebo. Kwavolumesnadevices, ufunguo ni njia ya kontena (container path). - Mfuatano (sequences) huongezewa.
dns,dns_search,expose,tmpfsnaexternal_linkshuunganishwa pamoja. Msingi wenyeexpose: ["3000"]ukija kuunganishwa na ubatilishaji wenye["4000", "5000"], matokeo yake ni["3000", "4000", "5000"].
Mfuatano minne hubeba ufunguo wa utambulisho, hivyo viingizo vinavyolingana kwenye ufunguo huo huunganishwa badala ya kuongezewa. volumes, secrets na configs hulinganishwa kwa kutumia target. ports hulinganishwa kwa kutumia mchanganyiko wa ip, target, published na protocol.
Soma sheria hiyo ya ports mara mbili, kwa sababu ndiyo mtego. Viingizo viwili vya port ni viingizo sawa pale tu sehemu zote nne zinapokubaliana. Badilisha sehemu yoyote kati ya hizo na Compose itaona port ya pili isiyohusiana, hivyo itahifadhi zote mbili.
Kwa nini port yako bado imechapishwa baada ya override
Faili la msingi linalochapisha huduma kwenye kila interface:
services:
web:
image: nginx:1.27
ports:
- "8080:80"Override iliyoandikwa ili kuifunga kwenye localhost pekee, kwa sababu reverse proxy itakaa mbele yake:
services:
web:
ports:
- "127.0.0.1:8080:80"Thibitisha matokeo kabla ya kudhani kuwa imefanya kazi.
docker compose -f compose.yaml -f compose.prod.yaml configIngizo zote mbili zimo kwenye matokeo. Sehemu ya ip inatofautiana, 0.0.0.0 dhidi ya 127.0.0.1, kwa hivyo hizo ni port mbili tofauti kwa kadiri ya muunganiko (merge) unavyohusika, na binding ya umma uliyojaribu kuiondoa bado imo kwenye modeli. Hilo ni muhimu zaidi kwenye Docker kuliko kwingineko, kwa sababu port iliyochapishwa huandikwa kwenye iptables kabla ya sheria zako za firewall. Utaratibu huu umeelezwa katika kwa nini port za Docker zilizochapishwa hupita ufw.
Kuna suluhu mbili. Ile ya wazi ni tag ya !override, ambayo hubadilisha attribute nzima na kuruka sheria za muunganiko:
services:
web:
ports: !override
- "127.0.0.1:8080:80"!override inahitaji Compose v2.24.4 au mpya zaidi. Suluhu inayoweza kubebeka haihitaji tag yoyote: acha ports nje ya faili la msingi kabisa na uitangaze kwenye faili mahususi za mazingira pekee. Hakuna cha kuunganisha inamaanisha hakuna cha kuvuja. Huo ndio muundo unaotumiwa katika mfano wa kazi hapa chini.
Kufuta thamani kutoka kwenye faili ya msingi
!reset huondoa sifa, na kuirejesha kwenye thamani yake ya awali au kuifanya kuwa null. Inahitaji thamani ili ifanye kazi, lakini huipuuza, kwa hivyo andika kitu chochote sahihi lakini kisicho na maudhui.
services:
web:
ports: !reset []
environment:
DEBUG: !reset null!reset inahitaji Compose v2.24 au toleo jipya zaidi. Itumie wakati faili ya msingi si yako na huwezi kuibadilisha, kwa mfano kipande cha faili (fragment) kutoka kwa mtoa huduma unachokitumia. Stack iliyochapishwa na msanidi wa juu ni mfano halisi wa hali hii: faili ya Compose iliyo nyuma ya workspace ya AFFiNE inayojiendesha yenyewe inatangaza container nne ambazo hukuziandika wewe, na !reset inakuwezesha kufuta sifa moja kwenye mojawapo ya container hizo bila kulazimika kufanya forking ya faili hiyo na kubeba jukumu la kuifuatilia.
include, kwa ajili ya stack zilizokusanywa kutoka sehemu mbalimbali
include huvuta programu nyingine ya Compose kwenye modeli yako. Hii ni elementi ya ngazi ya juu, si flag.
include:
- path: ../commons/compose.yamlKila njia katika include hupakiwa kama modeli yake ya programu ya Compose, ikiwa na saraka yake ya mradi, kwa hivyo njia za kadiri (relative paths) ndani ya faili hiyo hutatuliwa kulingana na saraka ya faili hiyo yenyewe. Hiyo ndiyo tofauti halisi na -f, na ndiyo sababu include ndiyo zana sahihi wakati kipande hicho kipo kwenye folda nyingine au hazina (repository) nyingine. Hiyo ndiyo sura ya kawaida ya stack ya vendor ambayo hukuandika wewe: faili ya Compose yenye huduma nyingi iliyo nyuma ya usakinishaji wa Authentik SSO unaojiendesha inaweza kukaa kwenye saraka yake yenyewe huku njia zake za kadiri zikiwa salama, wakati faili yako inabaki kuhusu huduma zako mwenyewe.
Fomu ndefu inakubali chaguzi ndogo (sub-options).
include:
- path:
- ../monitoring/compose.yaml
- ../monitoring/compose.vps.yaml
project_directory: ../monitoring
env_file: ../monitoring/.envpath hukubali orodha, na faili hizo huunganishwa pamoja kwa kutumia sheria za kawaida kabla ya matokeo kujiunga na modeli yako. project_directory huweka njia ya msingi inayotumiwa kutatua njia za kadiri katika faili iliyojumuishwa. env_file huipa faili iliyojumuishwa vigezo vyake (variables) kwa ajili ya interpolation, jambo linalozuia kipande kilichoshirikiwa kusoma kimya kimya .env ya mradi wako. include inahitaji Compose v2.20.0 au mpya zaidi. Chaguzi hizo hizo zinafaa kwa add-on ya kontena moja kwenye stack unayoendesha tayari, tuseme Halcyon, ambayo hubadilisha muonekano wa maktaba ya Jellyfin kuwa duka la kukodisha la miaka ya 90: faili yake huhifadhi tag yake ya image na env_file yake yenyewe, kwa hivyo kuiboresha (upgrade) hakumaanishi kugusa faili ambayo stack yako ya media inakaa.
Majina ya rasilimali yanayojirudia kati ya faili yako na faili iliyojumuishwa huripotiwa kama hitilafu badala ya kuunganishwa kimya kimya, na hilo ni la makusudi. Ili kubadilisha kitu ambacho faili iliyojumuishwa inatangaza, weka mabadiliko hayo katika compose.override.yaml: override hutumika kwenye modeli iliyokusanywa, kwa hivyo inaweza kugusa rasilimali zilizojumuishwa bila kugongana nazo. Tabia hiyo hulipa zaidi ukiwa na stack ambayo faili yake ya upstream huandikwa upya kila wakati wa release, kama vile seva za picha zenye kontena nyingi zilizolinganishwa katika PhotoPrism dhidi ya Immich, ambapo binding ya localhost au volume ya ziada inapaswa kuwa kwenye override yako badala ya faili ambayo upgrade inayofuata itachukua nafasi yake.
Kwa ufupi: include huunganisha programu tofauti, -f huweka usanidi (configuration) juu ya programu moja.
Mgawanyo wa dev na prod kwenye VPS moja
Huu hapa ni muundo mzima katika faili tatu. Faili ya msingi inatangaza kile ambacho ni kweli kila mahali, na haichapishi port yoyote.
name: myapp
services:
app:
image: ghcr.io/example/app:1.4.2
environment:
DATABASE_URL: postgres://app:${POSTGRES_PASSWORD}@db:5432/app
LOG_LEVEL: info
depends_on:
db:
condition: service_healthy
restart: unless-stopped
db:
image: postgres:16
environment:
POSTGRES_USER: app
POSTGRES_DB: app
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d app"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
volumes:
db_data:Sharti la depends_on ndilo linalofanya programu kusubiri database inayojibu badala ya container iliyopo tu, kama ilivyoelezwa katika healthchecks na masharti ya depends_on. POSTGRES_PASSWORD inachukuliwa kutoka kwenye faili ya .env ya mradi, ambayo haipaswi kamwe kuwekwa kwenye git. Tazama faili za env na siri za Compose kwa njia salama zaidi.
Inayofuata ni compose.override.yaml, ambayo Compose huipakia yenyewe. Hili ni faili la msanidi programu.
services:
app:
build: .
command: npm run dev
environment:
LOG_LEVEL: debug
ports:
- "3000:3000"
volumes:
- ./src:/app/src
db:
ports:
- "127.0.0.1:5432:5432"Kwenye laptop, docker compose up tupu huunganisha faili hizo mbili. command inachukua nafasi ya image default kwa sababu ina thamani moja. LOG_LEVEL inachukua nafasi ya info kwa sababu environment huunganisha kwa kutumia key. Bind mount na port mbili zilizochapishwa ni nyongeza safi, na port ya database imefungwa kwenye localhost ili laptop iliyo kwenye mtandao wa pamoja isitoe PostgreSQL kwa chumba kizima.
Mwisho, compose.prod.yaml. Jina lake si lile ambalo Compose hutafuta, kwa hivyo halipakii kwa bahati mbaya.
services:
app:
ports:
- "127.0.0.1:8000:3000"
deploy:
resources:
limits:
memory: 512MKwenye VPS unataja faili zote mbili, na kitendo hicho cha kutaja ndicho kinachozuia override.
docker compose -f compose.yaml -f compose.prod.yaml config
docker compose -f compose.yaml -f compose.prod.yaml up -d
docker compose -f compose.yaml -f compose.prod.yaml psps inapaswa kuorodhesha huduma zote mbili kama zinazoendelea, huku db ikionyesha (healthy). Kwa sababu umepitisha -f, compose.override.yaml haikusomwa, kwa hivyo amri ya dev, source bind mount na port 3000 ya umma haziwezi kufikia production ingawa faili ipo kwenye saraka moja. Port 8000 iko kwenye localhost pekee, tayari kwa proxy: tazama kuendesha programu kadhaa nyuma ya Traefik unapoongeza huduma ya pili.
Weka COMPOSE_FILE=compose.yaml:compose.prod.yaml katika .env ya seva na amri zako nyingine zitarudi kuwa docker compose logs -f app ya kawaida.
Stack ya huduma moja hupata umbo sawa, kwa sababu kifuatiliaji cha mazoezi cha openGym kinachojiendesha lazima kijibu kupitia TLS nyuma ya proxy kabla ya kusajili passkey ya kwanza, na faili ya msingi isiyo na ports ndani yake ndiyo inayozuia binding ya umma isiyokusudiwa kuwahi proxy kufanya kazi.
Soma modeli iliyounganishwa kabla ya kupeleka (deploy)
docker compose config huchapisha modeli iliyounganishwa kikamilifu na iliyokamilishwa (interpolated). Hii si hakiki ya awali (preview). Ni ingizo kamili ambalo Compose itafanyia kazi, kwa hivyo matokeo yanapokinzana na matarajio yako, matokeo ndiyo sahihi.
docker compose -f compose.yaml -f compose.prod.yaml config
docker compose -f compose.yaml -f compose.prod.yaml config --no-interpolate
docker compose -f compose.yaml -f compose.prod.yaml config --services--no-interpolate huacha ${VAR} bila kupanuliwa. Itumie kabla ya kubandika matokeo popote, kwa sababu config ya kawaida huchapisha kila siri (secret) iliyotatuliwa kwa maandishi wazi. --services huorodhesha majina ya huduma pekee, ambayo ni njia ya haraka ya kuthibitisha kuwa include imeleta kile ulichotarajia.
Njia za kufeli, na utakachokiona
no configuration file provided: not found. Compose haikupata chochote cha kusoma. Upo nje ya saraka ya mradi, au COMPOSE_FILE inataja njia ambayo haipo. Compose hutafuta saraka za juu kwa ajili ya faili msingi ya kawaida, lakini haitafuti popote kwa ajili ya faili uliyoiita wewe mwenyewe.
WARN[0000] The "POSTGRES_PASSWORD" variable is not set. Defaulting to a blank string. Interpolation hutatuliwa dhidi ya faili ya mradi ya .env na mazingira ya shell, na saraka ya mradi hapa ni saraka ya faili ya kwanza ya -f. Kupeleka (deploy) kutoka saraka tofauti na ile iliyo na .env hukupa onyo hili na kisha database inayokataa kila muunganisho.
Marekebisho yako ya override hayaonekani kwenye docker compose config. Aidha umepitisha -f, ambayo huzima upakiaji wa kiotomatiki wa override, au Compose imepata compose.yaml katika saraka ya juu na faili yako ya override haipo karibu nayo. Kuendesha docker compose config bila hoja nyingine yoyote hukuambia ni modeli gani Compose inajenga kweli.
Bind mount ni tupu na Docker imeunda saraka ambayo hukuomba. Njia ya relative ilitatuliwa dhidi ya saraka ya faili ya kwanza. Rekebisha njia hiyo, pitisha --project-directory, au hamisha kipande hicho nyuma ya include.
Containers zinarudi na majina mapya na volume inaonekana tupu. Jina la mradi limebadilika, kwa sababu jina la mradi hufuata saraka ya faili ya kwanza. Ongeza name: ya kiwango cha juu kwenye faili msingi na upeaji majina utaacha kuhama. Volume ya zamani bado ipo chini ya kiambishi awali cha zamani, na docker volume ls itakuonyesha.
Port uliyoiondoa kwenye override bado iko wazi. Muunganiko wa ports uliambatanisha badala ya kubadilisha. Thibitisha na docker compose config, kisha tumia !override au hamisha ports nje ya faili msingi.
FAQ
Je, Compose hupakia compose.override.yaml kiotomatiki?
Ndiyo, unapoendesha docker compose bila kutumia flag ya -f. Compose hutafuta saraka ya sasa na saraka mama kwa ajili ya compose.yaml au docker-compose.yaml, na ikiwa faili ya override ipo kando yake, faili hiyo hupakiwa ya pili. Majina yanayotambulika ni compose.override.yaml, compose.override.yml, docker-compose.override.yml na docker-compose.override.yaml. Kupitisha -f yoyote huzima utendaji huu, hivyo docker compose -f compose.yaml up husoma faili moja pekee.
Faili nyingi za -f huunganishwa kwa mpangilio upi?
Kutoka kushoto kwenda kulia. Compose hujenga usanidi kwa mpangilio unaotoa faili hizo, na kila faili hufuta na kuongezea zile zilizotangulia, hivyo faili ya mwisho kwenye mstari ndiyo inayoshinda katika mgongano wowote. Orodha ileile lazima itumike kwa kila amri katika mradi huo, ndiyo maana ya COMPOSE_FILE=compose.yaml:compose.prod.yaml.
Kwa nini port yangu bado imechapishwa baada ya kuifanyia override?
Kwa sababu entries za ports hutambuliwa kwa mkusanyiko mzima wa ip, target, published na protocol. Override ya 127.0.0.1:8080:80 dhidi ya msingi wa 8080:80 hutofautiana katika sehemu ya ip, hivyo Compose huichukulia kama port ya pili na kuhifadhi zote mbili. Endesha docker compose config na utaona entries hizo mbili. Tumia ports: !override kwenye Compose v2.24.4 au mpya zaidi, au acha ports nje ya faili ya msingi ili kusiwe na kitu cha kuunganishwa nacho.
Kuna tofauti gani kati ya include na -f?
-f huweka faili kadhaa juu ya programu moja, na kila njia (path) ya jamaa katika kila faili hutatuliwa dhidi ya saraka ya faili ya kwanza. include huleta programu tofauti ya Compose, na kila njia iliyojumuishwa huhifadhi saraka yake ya mradi, hivyo njia zake za jamaa hutatuliwa dhidi yake yenyewe. Tumia -f kwa matabaka ya mazingira ya stack yako, na include kwa sehemu inayotunzwa mahali pengine. include inahitaji Compose v2.20.0 au mpya zaidi.
Ninaondoaje thamani iliyowekwa na faili ya msingi?
Tumia tag ya !reset kwenye Compose v2.24 au mpya zaidi. Andika ports: !reset [] au MY_VAR: !reset null katika faili ya override na sifa hiyo itarudi kwenye thamani yake ya awali au kuwa null. Thamani unayoiweka kwenye tag hiyo inahitajika lakini hupuuzwa. Ikiwa unataka kubadilisha sifa badala ya kuifuta, !override hufanya hivyo, na inahitaji v2.24.4 au mpya zaidi.