ฉันใหม่สำหรับนักเทียบท่าและมันไม่ชัดเจนว่าจะเข้าถึงฐานข้อมูลภายนอกจากคอนเทนเนอร์ได้อย่างไร เป็นวิธีที่ดีที่สุดในรหัสยากในสตริงการเชื่อมต่อ?
# Dockerfile
ENV DATABASE_URL amazon:rds/connection?string
ฉันใหม่สำหรับนักเทียบท่าและมันไม่ชัดเจนว่าจะเข้าถึงฐานข้อมูลภายนอกจากคอนเทนเนอร์ได้อย่างไร เป็นวิธีที่ดีที่สุดในรหัสยากในสตริงการเชื่อมต่อ?
# Dockerfile
ENV DATABASE_URL amazon:rds/connection?string
คำตอบ:
คุณสามารถส่งผ่านตัวแปรสภาพแวดล้อมไปยังคอนเทนเนอร์ด้วย-e
แฟล็ก
ตัวอย่างจากสคริปต์เริ่มต้น:
sudo docker run -d -t -i -e REDIS_NAMESPACE='staging' \
-e POSTGRES_ENV_POSTGRES_PASSWORD='foo' \
-e POSTGRES_ENV_POSTGRES_USER='bar' \
-e POSTGRES_ENV_DB_NAME='mysite_staging' \
-e POSTGRES_PORT_5432_TCP_ADDR='docker-db-1.hidden.us-east-1.rds.amazonaws.com' \
-e SITE_URL='staging.mysite.com' \
-p 80:80 \
--link redis:redis \
--name container_name dockerhub_id/image_name
หรือถ้าคุณไม่ต้องการให้มีค่าในบรรทัดคำสั่งที่จะแสดงโดยps
ฯลฯ-e
สามารถดึงค่าจากสภาพแวดล้อมปัจจุบันถ้าคุณเพียงแค่ให้มันโดยไม่ต้อง=
:
sudo PASSWORD='foo' docker run [...] -e PASSWORD [...]
หากคุณมีตัวแปรสภาพแวดล้อมมากมายและโดยเฉพาะอย่างยิ่งหากพวกเขาตั้งใจจะเป็นความลับคุณสามารถใช้ไฟล์ env :
$ docker run --env-file ./env.list ubuntu bash
แฟล็ก --env-file ใช้ชื่อไฟล์เป็นอาร์กิวเมนต์และคาดว่าแต่ละบรรทัดจะอยู่ในรูปแบบ VAR = VAL จำลองอาร์กิวเมนต์ที่ส่งผ่านไปยัง --env บรรทัดความคิดเห็นต้องขึ้นต้นด้วย #
export PASSWORD=foo
แทนและตัวแปรจะถูกส่งผ่านไปdocker run
เป็นตัวแปรสภาพแวดล้อมทำให้การdocker run -e PASSWORD
ทำงาน
คุณสามารถส่งผ่านการใช้-e
พารามิเตอร์พร้อมdocker run ..
คำสั่งตามที่กล่าวถึงที่นี่และตามที่ระบุไว้โดย @errata
อย่างไรก็ตามข้อเสียที่เป็นไปได้ของวิธีการนี้คือข้อมูลประจำตัวของคุณจะปรากฏในรายการกระบวนการที่คุณเรียกใช้
ที่จะทำให้มันปลอดภัยมากขึ้นคุณอาจเขียนประจำตัวของคุณในแฟ้มการกำหนดค่าและทำdocker run
ด้วย--env-file
ตามที่กล่าวไว้ที่นี่ จากนั้นคุณสามารถควบคุมการเข้าถึงไฟล์ปรับแต่งนั้นเพื่อให้คนอื่นที่มีสิทธิ์เข้าถึงเครื่องนั้นจะไม่เห็นข้อมูลรับรองของคุณ
--env-file
เมื่อคุณใช้--env
ค่า env ของคุณจะถูกยกมา / หลบหนีด้วยความหมายมาตรฐานของเชลล์สิ่งที่คุณใช้ แต่เมื่อใช้--env-file
ค่าที่คุณจะได้รับภายในคอนเทนเนอร์ของคุณจะแตกต่างกัน คำสั่งเรียกใช้นักเทียบท่าเพิ่งอ่านไฟล์ทำการแยกขั้นพื้นฐานและส่งค่าผ่านไปยังคอนเทนเนอร์มันไม่เทียบเท่ากับที่เชลล์ทำงานของคุณ เพียงแค่ gotcha ขนาดเล็กที่ต้องระวังหากคุณแปลง--env
รายการเป็น--env-file
กลุ่ม
หากคุณใช้ 'นักเทียบท่าเขียน' เป็นวิธีการหมุนตู้คอนเทนเนอร์ของคุณมีวิธีที่มีประโยชน์จริง ๆ ในการส่งตัวแปรสภาพแวดล้อมที่กำหนดไว้บนเซิร์ฟเวอร์ของคุณไปยังคอนเทนเนอร์นักเทียบท่า
ในdocker-compose.yml
ไฟล์ของคุณสมมติว่าคุณกำลังหมุนคอนเทนเนอร์ hapi-js พื้นฐานและโค้ดดูเหมือนว่า:
hapi_server:
container_name: hapi_server
image: node_image
expose:
- "3000"
สมมติว่าเซิร์ฟเวอร์ภายในเครื่องที่โปรเจ็กต์ docker ของคุณเปิดอยู่มีตัวแปรสภาพแวดล้อมชื่อ 'NODE_DB_CONNECT' ที่คุณต้องการส่งต่อไปยังคอนเทนเนอร์ hapi-js ของคุณและคุณต้องการให้ชื่อใหม่เป็น 'HAPI_DB_CONNECT' จากนั้นในdocker-compose.yml
ไฟล์คุณจะส่งผ่านตัวแปรสภาพแวดล้อมท้องถิ่นไปยังคอนเทนเนอร์และเปลี่ยนชื่อดังนี้:
hapi_server:
container_name: hapi_server
image: node_image
environment:
- HAPI_DB_CONNECT=${NODE_DB_CONNECT}
expose:
- "3000"
ฉันหวังว่านี่จะช่วยคุณหลีกเลี่ยงการเข้ารหัสสตริงการเชื่อมต่อฐานข้อมูลในไฟล์ใด ๆ ในคอนเทนเนอร์ของคุณ!
การใช้docker-compose
คุณสามารถสืบทอดตัวแปร env ใน docker-compose.yml และต่อมา Dockerfile ใด ๆ ที่ถูกเรียกใช้docker-compose
เพื่อสร้างภาพ สิ่งนี้มีประโยชน์เมื่อDockerfile
RUN
คำสั่งควรดำเนินการคำสั่งเฉพาะสำหรับสภาพแวดล้อม
(เปลือกของคุณมี RAILS_ENV=development
อยู่แล้วในสภาพแวดล้อม)
นักเทียบท่า-compose.yml :
version: '3.1'
services:
my-service:
build:
#$RAILS_ENV is referencing the shell environment RAILS_ENV variable
#and passing it to the Dockerfile ARG RAILS_ENV
#the syntax below ensures that the RAILS_ENV arg will default to
#production if empty.
#note that is dockerfile: is not specified it assumes file name: Dockerfile
context: .
args:
- RAILS_ENV=${RAILS_ENV:-production}
environment:
- RAILS_ENV=${RAILS_ENV:-production}
Dockerfile :
FROM ruby:2.3.4
#give ARG RAILS_ENV a default value = production
ARG RAILS_ENV=production
#assign the $RAILS_ENV arg to the RAILS_ENV ENV so that it can be accessed
#by the subsequent RUN call within the container
ENV RAILS_ENV $RAILS_ENV
#the subsequent RUN call accesses the RAILS_ENV ENV variable within the container
RUN if [ "$RAILS_ENV" = "production" ] ; then echo "production env"; else echo "non-production env: $RAILS_ENV"; fi
วิธีนี้ฉันไม่จำเป็นต้องระบุตัวแปรสภาพแวดล้อมในไฟล์หรือdocker-compose
build
/ up
คำสั่ง:
docker-compose build
docker-compose up
ใช้-e
หรือ - ค่า env เพื่อตั้งค่าตัวแปรสภาพแวดล้อม (ค่าเริ่มต้น [])
ตัวอย่างจากสคริปต์เริ่มต้น:
docker run -e myhost='localhost' -it busybox sh
หากคุณต้องการใช้หลายสภาพแวดล้อมจากบรรทัดคำสั่งก่อนที่ตัวแปรสภาพแวดล้อมทุกตัวจะใช้-e
แฟล็ก
ตัวอย่าง:
sudo docker run -d -t -i -e NAMESPACE='staging' -e PASSWORD='foo' busybox sh
หมายเหตุ: ตรวจสอบให้แน่ใจว่าใส่ชื่อคอนเทนเนอร์หลังตัวแปรสภาพแวดล้อมไม่ใช่ก่อนหน้านั้น
หากคุณต้องการตั้งค่าตัวแปรจำนวนมากให้ใช้--env-file
แฟล็ก
ตัวอย่างเช่น,
$ docker run --env-file ./my_env ubuntu bash
สำหรับความช่วยเหลืออื่น ๆ ให้ดูที่วิธีใช้ Docker:
$ docker run --help
เอกสารอย่างเป็นทางการ: https://docs.docker.com/compose/environment-variables/
ubuntu bash
? มันใช้กับภาพที่สร้างด้วยอูบุนตูเป็นภาพฐานหรือทุกภาพหรือไม่?
-e
โต้แย้งอายุที่ผ่านมา! ฉันไม่สามารถแม้แต่จะเข้าใจว่าทำไมพวกเขาถึงทำสิ่งนี้จำเป็น ...
มีแฮ็คที่ดีวิธีการวางท่อตัวแปรสภาพแวดล้อมของเครื่องโฮสต์ไปยังคอนเทนเนอร์นักเทียบท่า:
env > env_file && docker run --env-file env_file image_name
ใช้เทคนิคนี้อย่างระมัดระวังเพราะ
env > env_file
จะถ่ายโอนทั้งหมดตัวแปรเครื่องโฮสต์ ENV ไปenv_file
และทำให้พวกเขาสามารถเข้าถึงได้ในภาชนะที่ทำงาน
สำหรับ Amazon AWS ECS / ECR คุณควรจัดการตัวแปรสภาพแวดล้อมของคุณ ( โดยเฉพาะความลับ ) ผ่าน S3 bucket ส่วนตัว ดูโพสต์บล็อกวิธีการจัดการความลับสำหรับการประยุกต์ใช้ Amazon EC2 คอนเทนเนอร์บริการโดยใช้ Amazon S3 และหาง
อีกวิธีหนึ่งคือการใช้พลังของ/usr/bin/env
:
docker run ubuntu env DEBUG=1 path/to/script.sh
หากคุณมีตัวแปรสภาพแวดล้อมในเครื่องenv.sh
และต้องการตั้งค่าเมื่อคอนเทนเนอร์เริ่มต้นคุณสามารถลอง
COPY env.sh /env.sh
COPY <filename>.jar /<filename>.jar
ENTRYPOINT ["/bin/bash" , "-c", "source /env.sh && printenv && java -jar /<filename>.jar"]
คำสั่งนี้จะเริ่มต้นคอนเทนเนอร์ด้วย bash shell (ฉันต้องการ bash shell เนื่องจากsource
เป็นคำสั่ง bash), แหล่งที่มาของenv.sh
ไฟล์ (ซึ่งตั้งค่าตัวแปรสภาพแวดล้อม) และเรียกใช้ไฟล์ jar
env.sh
ลักษณะเช่นนี้
#!/bin/bash
export FOO="BAR"
export DB_NAME="DATABASE_NAME"
ฉันเพิ่มprintenv
คำสั่งเท่านั้นเพื่อทดสอบว่าคำสั่งแหล่งที่มาจริงทำงาน คุณควรลบออกเมื่อคุณยืนยันว่าคำสั่ง source ทำงานได้ดีหรือตัวแปรสภาพแวดล้อมจะปรากฏในบันทึกนักเทียบท่าของคุณ
--env-file
หาเรื่องกับdocker run
คำสั่ง ตัวอย่างเช่นหากคุณกำลังปรับใช้แอปพลิเคชันโดยใช้ Google App Engine และแอปที่ทำงานอยู่ภายในคอนเทนเนอร์นั้นต้องการตัวแปรสภาพแวดล้อมที่ตั้งไว้ภายใน Docker Container คุณไม่มีวิธีการโดยตรงในการตั้งค่าตัวแปรสภาพแวดล้อมเนื่องจากคุณไม่สามารถควบคุมdocker run
คำสั่งได้ . ในกรณีเช่นนี้คุณสามารถมีสคริปต์ที่ถอดรหัสตัวแปร env โดยใช้คำพูด KMS และเพิ่มลงในสิ่งenv.sh
ที่สามารถจัดหามาเพื่อตั้งค่าตัวแปร env
.
(dot) คำสั่งที่มีอยู่ในปกติแทนsh
source
( source
เหมือนกับ.
)
การใช้ jq เพื่อแปลง env เป็น JSON:
env_as_json=`jq -c -n env`
docker run -e HOST_ENV="$env_as_json" <image>
ต้องใช้ jq เวอร์ชั่น1.6ขึ้นไป
ทำให้ pust นี้โฮสต์ env เป็น json, เป็นหลักเช่นนั้นใน Dockerfile:
ENV HOST_ENV (all env from the host as json)
docker run -e HOST_ENV="$env_as_json" <image>
? ในกรณีของฉันนักเทียบท่าดูเหมือนจะไม่สามารถแก้ไขตัวแปรหรือ subshells ( ${}
หรือ$()
) เมื่อส่งผ่านเป็นนักเทียบท่า args ตัวอย่างเช่น: A=123 docker run --rm -it -e HE="$A" ubuntu
จากนั้นภายในคอนเทนเนอร์นั้น: root@947c89c79397:/# echo $HE root@947c89c79397:/#
.... HE
ตัวแปรไม่สามารถทำได้
เรายังสามารถโฮสต์ตัวแปรสภาพแวดล้อมของเครื่องโดยใช้แฟล็ก -e และ $:
docker run -it -e MG_HOST=$MG_HOST -e MG_USER=$MG_USER -e MG_PASS=$MG_PASS -e MG_AUTH=$MG_AUTH -e MG_DB=$MG_DB -t image_tag_name_and_version
โดยใช้วิธีนี้ตั้งค่าตัวแปร env โดยอัตโนมัติด้วยชื่อของคุณในกรณีของฉัน (MG_HOST, MG_USER)
หากคุณใช้ python คุณสามารถเข้าถึงตัวแปร envment ภายใน Docker ได้
import os
host,username,password,auth,database=os.environ.get('MG_HOST'),os.environ.get('MG_USER'),os.environ.get('MG_PASS'),os.environ.get('MG_AUTH'),os.environ.get('MG_DB')
docker run --rm -it --env-file <(bash -c 'env | grep <your env data>')
เป็นวิธีการ grep ข้อมูลที่เก็บไว้ภายใน a .env
และส่งต่อไปยัง Docker โดยไม่มีการจัดเก็บข้อมูลใด ๆ ที่ไม่ปลอดภัย (ดังนั้นคุณจึงไม่สามารถดูdocker history
และหยิบกุญแจได้
สมมติว่าคุณมีสิ่งต่างๆมากมายที่คุณ.env
ชอบAWS :
AWS_ACCESS_KEY: xxxxxxx
AWS_SECRET: xxxxxx
AWS_REGION: xxxxxx
การทำงานนักเทียบท่าที่มี `` `run docker --rm -it --env-file <(bash -c 'env | grep AWS_') จะคว้ามันทั้งหมดและผ่านมันอย่างปลอดภัยเพื่อให้สามารถเข้าถึงได้จากภายในภาชนะ