2016-11-29 25 views
12

Tôi mới sử dụng Docker và tôi đang gặp khó khăn trong việc thiết lập vùng chứa docker như tôi muốn. Tôi có một ứng dụng nodejs có thể mất hai tham số khi bắt đầu. Ví dụ, tôi có thể sử dụngSử dụng lệnh docker run để chuyển đối số cho CMD trong Dockerfile

node server.js 0 dev

hoặc

node server.js 1 prod

để chuyển đổi giữa chế độ sản xuất và chế độ dev và xác định xem nó nên bật cụm trên. Bây giờ tôi muốn tạo hình ảnh Docker với lập luận để làm điều tương tự, điều duy nhất tôi có thể làm cho đến nay là để điều chỉnh Dockerfile để có một dòng

CMD [ "node", "server.js", "0", "dev"]

docker build -t me/app . để xây dựng docker.

Sau đó, docker run -p 9000:9000 -d me/app để chạy trình neo.

Nhưng nếu tôi muốn chuyển sang chế độ sản, tôi cần phải thay đổi Dockerfile CMD được

CMD [ "node", "server.js", "1", "prod"],

và tôi cần phải giết một tuổi lắng nghe trên cổng 9000 và xây dựng lại hình ảnh. Tôi ước gì tôi có thể có một cái gì đó giống như

docker run -p 9000:9000 environment=dev cluster=0 -d me/app

để tạo ra một hình ảnh và chạy nodejs lệnh với "môi trường" và "cụm" lập luận, vì vậy tôi không cần phải thay đổi Dockerfile và xây dựng lại các Docker nữa không. Làm thế nào tôi có thể thực hiện điều này?

Trả lời

17

Hãy chắc chắn rằng Dockerfile của bạn tuyên bố một biến môi trường with ENV:

ENV environment default_env_value 
ENV cluster default_cluster_value 

Dạng ENV <key> <value> có thể replaced inline .

Sau đó, bạn có thể pass an environment variable with docker run

docker run -p 9000:9000 -e environment=dev -e cluster=0 -d me/app 

Hoặc bạn có thể set them through your compose file:

node: 
    environment: 
    - environment=dev 
    - cluster=0 

Dockerfile bạn CMD có thể sử dụng biến môi trường, nhưng, như đã đề cập trong issue 5509, bạn cần phải làm như vậy trong một sh -c biểu mẫu:

CMD ["sh", "-c", "node server.js ${cluster} ${environment}"] 

Giải thích là shell chịu trách nhiệm mở rộng các biến môi trường, chứ không phải Docker. Khi bạn sử dụng cú pháp JSON JSON, bạn đang yêu cầu rõ ràng lệnh của bạn bỏ qua trình bao và được thực hiện trực tiếp.

Cùng ý tưởng với Builder RUN (áp dụng cho CMD cũng):

Không giống như các hình thức vỏ, hình thức exec không gọi một lệnh shell.
Điều này có nghĩa là việc xử lý vỏ bình thường không xảy ra.

Ví dụ: RUN [ "echo", "$HOME" ] sẽ không thực hiện thay thế biến trên $HOME. Nếu bạn muốn xử lý vỏ thì hãy sử dụng biểu mẫu trình bao hoặc thực thi một trình bao trực tiếp, ví dụ: RUN [ "sh", "-c", "echo $HOME" ].

Khi sử dụng biểu mẫu thực thi và thực hiện trực tiếp trình bao, như trong trường hợp đối với biểu mẫu trình bao, đó là trình bao đang thực hiện mở rộng biến môi trường, chứ không phải trình neo.

+0

Làm cách nào tôi có thể sử dụng ENV trong tệp docker CMD, bạn có thể cho tôi ví dụ không? – Jaaaaaaay

+0

@Jaaaaaaay 'ENV' là khai báo trong' Dockerfile' của bạn (đọc https://docs.docker.com/engine/reference/builder/#/env), sau đó nó sẽ được định giá bởi 'docker run -e myvar = myvalue' – VonC

+0

@Jaaaaaaay Tôi đã chỉnh sửa câu trả lời để giải quyết câu hỏi của bạn. – VonC

4

Cách thông thường để làm điều này trong các thùng chứa Docker là để vượt qua trong biến môi trường:

docker run -p 9000:9000 -e NODE_ENV=dev -e CLUSTER=0 -d me/app 
9

Một lựa chọn khác là sử dụng ENTRYPOINT để xác định rằng node là thực thi để chạy và CMD để cung cấp các luận cứ. Tài liệu có ví dụ trong Exec form ENTRYPOINT example.

Sử dụng phương pháp này, Dockerfile của bạn sẽ trông giống như

FROM ... 

ENTRYPOINT [ "node", "server.js" ] 
CMD [ "0", "dev" ] 

Chạy nó trong dev sẽ sử dụng cùng một lệnh

docker run -p 9000:9000 -d me/app 

và chạy nó trong sản bạn sẽ vượt qua các thông số để chạy command

docker run -p 9000:9000 -d me/app 1 prod 

Bạn có thể muốn bỏ qua hoàn toàn CMD và luôn vượt qua 0 dev hoặc 1 prod làm đối số cho lệnh chạy. Bằng cách đó bạn không vô tình bắt đầu một vùng chứa prod trong dev hoặc một container dev trong prod.

Các vấn đề liên quan