Có thể đặt biến ENV của docker thành kết quả của một lệnh không? Giống:
ENV MY_VAR whoami
tôi muốn MY_VAR nhận giá trị "root" hoặc bất kỳ giá trị nào mà whoami trả về
Câu trả lời:
Như một phần bổ sung cho câu trả lời DarkSideF.
Bạn nên biết rằng mỗi dòng / lệnh trong Dockerfile được chạy trong một vùng chứa khác.
Bạn có thể làm điều gì đó như sau:
RUN export bleah=$(hostname -f);echo $bleah;
Điều này được chạy trong một vùng chứa duy nhất.
$bleah
là không có sẵn ở bất cứ đâu bên ngoài lệnh RUN này, thậm chí không trên dòng tiếp theo trong dockerfile cùng, hãy để một mình trong một hình ảnh nó dựa tắt. Tính năng thực sự bị thiếu rõ ràng từ docker ở đây, có vẻ như ghi và đọc từ một tệp là cách duy nhất để thực sự lưu trữ các biến (động) trong hình ảnh và chuyển chúng giữa các hình ảnh, điều này có vẻ siêu hacky.
Tôi đã gặp vấn đề tương tự và đã tìm thấy cách đặt biến môi trường là kết quả của hàm bằng cách sử dụng lệnh RUN trong dockerfile.
Ví dụ: tôi cần đặt SECRET_KEY_BASE cho ứng dụng Rails chỉ một lần mà không thay đổi như khi tôi chạy:
docker run -e SECRET_KEY_BASE="$(openssl rand -hex 64)"
Thay vào đó, tôi ghi vào chuỗi Dockerfile như:
RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" >> /etc/bash.bashrc'
và biến env của tôi có sẵn từ gốc, ngay cả sau khi đăng nhập bash. hoặc có thể
RUN /bin/bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" > /etc/profile.d/docker_init.sh'
thì biến nó có sẵn trong các lệnh CMD và ENTRYPOINT
Docker cache nó dưới dạng lớp và chỉ thay đổi nếu bạn thay đổi một số chuỗi trước nó.
Bạn cũng có thể thử các cách khác nhau để đặt biến môi trường.
*.sh
tệp nào bên trong /etc/profile.d/
được sử dụng để điền vào môi trường
Tại thời điểm này, một kết quả lệnh có thể được sử dụng với RUN export
, nhưng không thể được gán cho một ENV
biến.
Sự cố đã biết: https://github.com/docker/docker/issues/29110
Câu trả lời này là phản hồi cho @DarkSideF ,
Phương pháp mà anh ấy đang đề xuất như sau, trong Dockerfile
:
RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" >> /etc/bash.bashrc'
( thêm một bản xuất trong/etc/bash.bashrc
)
Nó tốt nhưng biến môi trường sẽ chỉ có sẵn cho quá trình /bin/bash
và nếu bạn cố gắng chạy ứng dụng docker của mình, chẳng hạn như ứng dụng Node.js, /etc/bash.bashrc
sẽ hoàn toàn bị bỏ qua và ứng dụng của bạn sẽ không có manh mối nào SECRET_KEY_BASE
khi thử. để truy cập process.env.SECRET_KEY_BASE
.
Đó là lý do tại sao ENV
từ khóa là thứ mà mọi người đang cố gắng sử dụng với lệnh động bởi vì mỗi khi bạn chạy vùng chứa của mình hoặc sử dụng một exec
lệnh, Docker sẽ kiểm tra ENV
và chuyển mọi giá trị trong quá trình hiện đang chạy (tương tự như -e
).
Một giải pháp là sử dụng trình bao bọc (tín dụng cho @duglin trong vấn đề github này ). Có một tệp trình bao bọc (ví dụ envwrapper
) trong gốc dự án của bạn chứa:
#!/bin/bash
export SECRET_KEY_BASE="$(openssl rand -hex 64)"
export ANOTHER_ENV "hello world"
$*
và sau đó trong Dockerfile
:
...
COPY . .
RUN mv envwrapper /bin/.
RUN chmod 755 /bin/envwrapper
CMD envwrapper myapp
Như một phần bổ sung cho câu trả lời của @ DarkSideF, nếu bạn muốn sử dụng lại kết quả của một lệnh trước đó trong Dockerfile
quá trình xây dựng của bạn, bạn có thể sử dụng cách giải quyết sau:
Ví dụ :
RUN echo "bla" > ./result
RUN echo $(cat ./result)
Đối với một cái gì đó rõ ràng hơn, bạn cũng có thể sử dụng ý chính sau đây cung cấp một CLI nhỏ được gọi là envstore.py
:
RUN envstore.py set MY_VAR bla
RUN echo $(envstore.py get MY_VAR)
Hoặc bạn có thể sử dụng thư viện python-dotenv có CLI tương tự.
Không chắc liệu đây có phải là thứ bạn đang tìm kiếm hay không, nhưng để đưa các vars ENV hoặc ARGS vào .Dockerfile, hãy xây dựng mẫu này hoạt động.
trong my_build.sh của bạn:
echo getting version of osbase image to build from
OSBASE=$(grep "osbase_version" .version | sed 's/^.*: //')
echo building docker
docker build -f \
--build-arg ARTIFACT_TAG=$OSBASE \
PATH_TO_MY.Dockerfile \
-t my_artifact_home_url/bucketname:$TAG .
để nhận ARG trong tệp .Dockerfile của bạn, đoạn mã có thể trông giống như sau:
FROM scratch
ARG ARTIFACT_TAG
FROM my_artifact_home_url/bucketname:${ARTIFACT_TAG}
cách khác để nhận ENV trong tệp .Dockerfile của bạn, đoạn mã có thể trông giống như sau:
FROM someimage:latest
ARG ARTIFACT_TAG
ENV ARTIFACT_TAG=${ARTIFACT_TAG}
ý tưởng là bạn chạy tập lệnh shell và gọi tệp .Dockerfile với các args được chuyển vào dưới dạng tùy chọn trên bản dựng.