Moby: 닀단계 λΉŒλ“œμ˜ λͺ¨λ“  이후 단계에 ENV 및 ARG μ„€μ • μœ μ§€

에 λ§Œλ“  2018λ…„ 06μ›” 26일  Β·  20μ½”λ©˜νŠΈ  Β·  좜처: moby/moby

기술

Afaik, μŠ€ν…Œμ΄μ§€κ°„μ— λ³€μˆ˜λ₯Ό 곡유 ν•  μˆ˜μžˆλŠ” 방법이 μ—†μŠ΅λ‹ˆλ‹€ (λ‚΄κ°€ ν‹€λ Έλ‹€λ©΄ μˆ˜μ • ν•΄μ£Όμ„Έμš”). ν•œ λΉŒλ“œ λ‹¨κ³„μ—μ„œ λ‹€μŒ λ‹¨κ³„λ‘œ κ³΅μœ ν•˜λ €λ©΄ ν•œ λ‹¨κ³„μ˜ λ””λ ‰ν† λ¦¬μ—μ„œ ν˜„μž¬ λ‹¨κ³„λ‘œ COPY νŒŒμΌμ„ κ³΅μœ ν•˜λŠ” 것이 μœ μΌν•œ μ˜΅μ…˜μž…λ‹ˆλ‹€. λΉŒλ“œ μ‹œκ°„ λ³€μˆ˜ 덀프λ₯Ό μ‚¬μš©ν•˜μ—¬ JSON 파일과 같은 것을 λΉŒλ“œ ν•  수 μžˆμ§€λ§Œμ΄ λ¬Έμ œλŠ” λ„ˆλ¬΄ 자주 λ°œμƒν•˜κ³  닀단계 λΉŒλ“œμ— λͺ¨λ“  μ’…λ₯˜μ˜ 미친 JSON ꡬ문 뢄석 λ¬Έμ œκ°€ λ„˜μΉ  것이라고 μƒκ°ν•©λ‹ˆλ‹€. 이것을 μžλ™ν™” ν•  수 μžˆμŠ΅λ‹ˆκΉŒ?

문제 μž¬ν˜„ 단계 :

FROM alpine:latest as base1
ARG v1=test
ENV v1=$v1
RUN echo ${v1}

FROM alpine:latest as base2
RUN echo ${v1}

받은 κ²°κ³Όλ₯Ό μ„€λͺ…ν•˜μ‹­μ‹œμ˜€.

docker build --no-cache  .
Step 4/6 : RUN echo ${v1}
---> Running in b60a3079864b
test

...

Step 5/6 : FROM alpine:latest as base2
---> 3fd9065eaf02
Step 6/6 : RUN echo ${v1}
---> Running in 1147977afd60

μ˜ˆμƒ ν•œ κ²°κ³Όλ₯Ό μ„€λͺ…ν•˜μ‹­μ‹œμ˜€.

docker build --no-cache --multistage-share-env --multistage-share-arg .
Step 4/6 : RUN echo ${v1}
---> Running in b60a3079864b
test

...

Step 5/6 : FROM alpine:latest as base2
---> 3fd9065eaf02
Step 6/6 : RUN echo ${v1}
---> Running in 1147977afd60
test

λ˜λŠ” λ„€μž„ μŠ€νŽ˜μ΄μŠ€μ™€ 같은 것을 μ‚¬μš©ν•˜μ—¬ ${base1.v1} λ₯Ό 보간 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

arebuilder kinquestion

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

μ •ν™•ν•©λ‹ˆλ‹€. ENV vars 및 ARG ν¬ν•¨ν•œ Dockerfile λͺ…λ Ήμ–΄λŠ” λΉŒλ“œ λ‹¨κ³„λ³„λ‘œ λ²”μœ„κ°€ μ§€μ •λ˜λ©° λ‹€μŒ λ‹¨κ³„μ—μ„œ λ³΄μ‘΄λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 이것은 μ˜λ„μ μœΌλ‘œ μ„€κ³„λœ κ²ƒμž…λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ _can_ _global_ ARG (첫 번째 λΉŒλ“œ 단계 이전에 μ„€μ •)λ₯Ό μ„€μ •ν•˜κ³  각 λΉŒλ“œ λ‹¨κ³„μ—μ„œ ν•΄λ‹Ή 값을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

ARG version_default=v1

FROM alpine:latest as base1
ARG version_default
ENV version=$version_default
RUN echo ${version}
RUN echo ${version_default}

FROM alpine:latest as base2
ARG version_default
RUN echo ${version_default}

--build-arg μ„ΈνŠΈμ—†μ΄ λΉŒλ“œ ν•  λ•Œ;

docker build --no-cache -<<'EOF'
ARG version_default=v1

FROM alpine:latest as base1
ARG version_default
ENV version=$version_default
RUN echo ${version}
RUN echo ${version_default}

FROM alpine:latest as base2
ARG version_default
RUN echo ${version_default}
EOF

이것은 λ‹€μŒμ„ μƒμ„±ν•©λ‹ˆλ‹€.

Sending build context to Docker daemon  2.048kB
Step 1/9 : ARG version_default=v1
Step 2/9 : FROM alpine:latest as base1
 ---> 3fd9065eaf02
Step 3/9 : ARG version_default
 ---> Running in 702c05d6f294
Removing intermediate container 702c05d6f294
 ---> 1b2cac6e7585
Step 4/9 : ENV version=$version_default
 ---> Running in 6fb73bc8cdb9
Removing intermediate container 6fb73bc8cdb9
 ---> 656d82ccb6d7
Step 5/9 : RUN echo ${version}
 ---> Running in 403c720d0031
v1
Removing intermediate container 403c720d0031
 ---> d6071c5bd329
Step 6/9 : RUN echo ${version_default}
 ---> Running in d5c76d7d3aaa
v1
Removing intermediate container d5c76d7d3aaa
 ---> 554df1d8584b
Step 7/9 : FROM alpine:latest as base2
 ---> 3fd9065eaf02
Step 8/9 : ARG version_default
 ---> Running in 92400e85c722
Removing intermediate container 92400e85c722
 ---> 5f0cb12f4448
Step 9/9 : RUN echo ${version_default}
 ---> Running in f38802f0d690
v1
Removing intermediate container f38802f0d690
 ---> 4b8caab7870a
Successfully built 4b8caab7870a

그리고 _with_ a --build-arg ;

docker build --no-cache --build-arg version_default=v2 -<<'EOF'
ARG version_default=v1

FROM alpine:latest as base1
ARG version_default
ENV version=$version_default
RUN echo ${version}
RUN echo ${version_default}

FROM alpine:latest as base2
ARG version_default
RUN echo ${version_default}
EOF
Sending build context to Docker daemon  2.048kB
Step 1/9 : ARG version_default=v1
Step 2/9 : FROM alpine:latest as base1
 ---> 3fd9065eaf02
Step 3/9 : ARG version_default
 ---> Running in 7f5dd5885859
Removing intermediate container 7f5dd5885859
 ---> 482ffb014095
Step 4/9 : ENV version=$version_default
 ---> Running in b6c6e9aa3489
Removing intermediate container b6c6e9aa3489
 ---> 83f1c0b82986
Step 5/9 : RUN echo ${version}
 ---> Running in 0805ec04fd20
v2
Removing intermediate container 0805ec04fd20
 ---> ef39d4bd6306
Step 6/9 : RUN echo ${version_default}
 ---> Running in f8747a5bfeeb
v2
Removing intermediate container f8747a5bfeeb
 ---> 72d497d25306
Step 7/9 : FROM alpine:latest as base2
 ---> 3fd9065eaf02
Step 8/9 : ARG version_default
 ---> Running in 57aa2e097787
Removing intermediate container 57aa2e097787
 ---> 45e167d234ce
Step 9/9 : RUN echo ${version_default}
 ---> Running in 8615cd6f6ab6
v2
Removing intermediate container 8615cd6f6ab6
 ---> 1674ad8d3b88
Successfully built 1674ad8d3b88

λͺ¨λ“  20 λŒ“κΈ€

μ •ν™•ν•©λ‹ˆλ‹€. ENV vars 및 ARG ν¬ν•¨ν•œ Dockerfile λͺ…λ Ήμ–΄λŠ” λΉŒλ“œ λ‹¨κ³„λ³„λ‘œ λ²”μœ„κ°€ μ§€μ •λ˜λ©° λ‹€μŒ λ‹¨κ³„μ—μ„œ λ³΄μ‘΄λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 이것은 μ˜λ„μ μœΌλ‘œ μ„€κ³„λœ κ²ƒμž…λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ _can_ _global_ ARG (첫 번째 λΉŒλ“œ 단계 이전에 μ„€μ •)λ₯Ό μ„€μ •ν•˜κ³  각 λΉŒλ“œ λ‹¨κ³„μ—μ„œ ν•΄λ‹Ή 값을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

ARG version_default=v1

FROM alpine:latest as base1
ARG version_default
ENV version=$version_default
RUN echo ${version}
RUN echo ${version_default}

FROM alpine:latest as base2
ARG version_default
RUN echo ${version_default}

--build-arg μ„ΈνŠΈμ—†μ΄ λΉŒλ“œ ν•  λ•Œ;

docker build --no-cache -<<'EOF'
ARG version_default=v1

FROM alpine:latest as base1
ARG version_default
ENV version=$version_default
RUN echo ${version}
RUN echo ${version_default}

FROM alpine:latest as base2
ARG version_default
RUN echo ${version_default}
EOF

이것은 λ‹€μŒμ„ μƒμ„±ν•©λ‹ˆλ‹€.

Sending build context to Docker daemon  2.048kB
Step 1/9 : ARG version_default=v1
Step 2/9 : FROM alpine:latest as base1
 ---> 3fd9065eaf02
Step 3/9 : ARG version_default
 ---> Running in 702c05d6f294
Removing intermediate container 702c05d6f294
 ---> 1b2cac6e7585
Step 4/9 : ENV version=$version_default
 ---> Running in 6fb73bc8cdb9
Removing intermediate container 6fb73bc8cdb9
 ---> 656d82ccb6d7
Step 5/9 : RUN echo ${version}
 ---> Running in 403c720d0031
v1
Removing intermediate container 403c720d0031
 ---> d6071c5bd329
Step 6/9 : RUN echo ${version_default}
 ---> Running in d5c76d7d3aaa
v1
Removing intermediate container d5c76d7d3aaa
 ---> 554df1d8584b
Step 7/9 : FROM alpine:latest as base2
 ---> 3fd9065eaf02
Step 8/9 : ARG version_default
 ---> Running in 92400e85c722
Removing intermediate container 92400e85c722
 ---> 5f0cb12f4448
Step 9/9 : RUN echo ${version_default}
 ---> Running in f38802f0d690
v1
Removing intermediate container f38802f0d690
 ---> 4b8caab7870a
Successfully built 4b8caab7870a

그리고 _with_ a --build-arg ;

docker build --no-cache --build-arg version_default=v2 -<<'EOF'
ARG version_default=v1

FROM alpine:latest as base1
ARG version_default
ENV version=$version_default
RUN echo ${version}
RUN echo ${version_default}

FROM alpine:latest as base2
ARG version_default
RUN echo ${version_default}
EOF
Sending build context to Docker daemon  2.048kB
Step 1/9 : ARG version_default=v1
Step 2/9 : FROM alpine:latest as base1
 ---> 3fd9065eaf02
Step 3/9 : ARG version_default
 ---> Running in 7f5dd5885859
Removing intermediate container 7f5dd5885859
 ---> 482ffb014095
Step 4/9 : ENV version=$version_default
 ---> Running in b6c6e9aa3489
Removing intermediate container b6c6e9aa3489
 ---> 83f1c0b82986
Step 5/9 : RUN echo ${version}
 ---> Running in 0805ec04fd20
v2
Removing intermediate container 0805ec04fd20
 ---> ef39d4bd6306
Step 6/9 : RUN echo ${version_default}
 ---> Running in f8747a5bfeeb
v2
Removing intermediate container f8747a5bfeeb
 ---> 72d497d25306
Step 7/9 : FROM alpine:latest as base2
 ---> 3fd9065eaf02
Step 8/9 : ARG version_default
 ---> Running in 57aa2e097787
Removing intermediate container 57aa2e097787
 ---> 45e167d234ce
Step 9/9 : RUN echo ${version_default}
 ---> Running in 8615cd6f6ab6
v2
Removing intermediate container 8615cd6f6ab6
 ---> 1674ad8d3b88
Successfully built 1674ad8d3b88

또 λ‹€λ₯Έ 방법은 μ—¬λŸ¬ 단계에 κΈ°λ³Έ μ»¨ν…Œμ΄λ„ˆλ₯Ό μ‚¬μš©ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

FROM alpine:latest as base
ARG version_default
ENV version=$version_default

FROM base
RUN echo ${version}

FROM base
RUN echo ${version}
docker build --build-arg=version_default=123 --no-cache .   
Sending build context to Docker daemon  92.67kB
Step 1/7 : FROM alpine:latest as base
 ---> 3fd9065eaf02
Step 2/7 : ARG version_default
 ---> Running in a1ebfdf79f07
Removing intermediate container a1ebfdf79f07
 ---> 3e78800ed9ea
Step 3/7 : ENV version=$version_default
 ---> Running in 105d94baac3f
Removing intermediate container 105d94baac3f
 ---> a14276ddc77b
Step 4/7 : FROM base
 ---> a14276ddc77b
Step 5/7 : RUN echo ${version}
 ---> Running in d92f9b48a6cc
123
Removing intermediate container d92f9b48a6cc
 ---> 6505fe2a14bb
Step 6/7 : FROM base
 ---> a14276ddc77b
Step 7/7 : RUN echo ${version}
 ---> Running in 1b748eea4ef3
123
Removing intermediate container 1b748eea4ef3
 ---> f3311d3ad27e
Successfully built f3311d3ad27e
Time: 0h:00m:04s

이것은 μ˜λ„μ μœΌλ‘œ μ„€κ³„λœ 것이기 λ•Œλ¬Έμ—μ΄ 문제λ₯Ό λ§ˆλ¬΄λ¦¬ν•˜κ² μŠ΅λ‹ˆλ‹€. μœ„μ˜ μ˜ˆκ°€ 더 λ§Žμ€ λ„μ›€μ΄λ˜κΈ°λ₯Ό λ°”λžλ‹ˆλ‹€. λŒ€ν™”λ₯Ό κ³„μ†ν•΄λ„λ©λ‹ˆλ‹€.

이것이 μ˜λ„μ μœΌλ‘œ μ„€κ³„λœ 것이라면 λ””μžμΈμ΄ 잘λͺ»λœ κ²ƒμž…λ‹ˆλ‹€. 단계간에 λ³€μˆ˜λ₯Ό κ³΅μœ ν•˜λŠ” κ°„κ²°ν•œ 방법이 μ—†μœΌλ©΄ DRYκ°€ λΆˆκ°€λŠ₯ν•©λ‹ˆλ‹€. λ§Žμ€ 단계가 λ™μΌν•œ λ³€μˆ˜μ— μ•‘μ„ΈμŠ€ν•΄μ•Όν•˜λŠ” ν”Όν•  μˆ˜μ—†κ³  제거 ν•  μˆ˜μ—†λŠ” 상황이 μžˆμŠ΅λ‹ˆλ‹€. μ •μ˜λ₯Ό λ³΅μ œν•˜λ©΄ 였λ₯˜κ°€ λ°œμƒν•˜κΈ° μ‰¬μš°λ―€λ‘œ 곡유 된 μ •μ˜λ₯Ό λͺ¨λ“  λ‹¨κ³„λ‘œ ν•΄ν‚Ήν•˜κΈ°μœ„ν•œ μƒμš©κ΅¬λ₯Ό λ³΅μ œν•©λ‹ˆλ‹€.

"κΈ°λ³Έ μ»¨ν…Œμ΄λ„ˆ"μ ‘κ·Ό 방식은 λͺ¨λ“  단계에 λŒ€ν•΄ κΈ°λ³Έ μ»¨ν…Œμ΄λ„ˆλ₯Ό μˆ˜μ •ν•˜κΈ° λ•Œλ¬Έμ— ν‘œν˜„λ ₯을 μ‹¬κ°ν•˜κ²Œ μ œν•œν•˜λŠ” 반면 쀑간 λ‹¨κ³„μ—μ„œ 각 단계에 ν•„μš”ν•œ 도ꡬλ₯Ό μ œκ³΅ν•˜λŠ” μ„œλ‘œ λ‹€λ₯Έ μ΅œμ†Œ κΈ°λ³Έ 이미지λ₯Ό μ‚¬μš©ν•΄μ•Όν•˜λŠ” μœ νš¨ν•œ μ‚¬μš© 사둀가 μžˆμŠ΅λ‹ˆλ‹€.

λΏ‘ 빡뀨
이 λ””μžμΈμ„ 재고 ν•  수 μžˆμŠ΅λ‹ˆκΉŒ?

λ‚΄λΆ€μ μœΌλ‘œ 만 μ‚¬μš©ν•  수 있고 주둜 λ‹€μ–‘ν•œ λΉŒλ“œμ— μ‚¬μš©λ˜λŠ” 11 개의 κΈ°λ³Έ 이미지가 μžˆμŠ΅λ‹ˆλ‹€. 11 개의 이미지가 닀쀑 단계 λΉŒλ“œμ˜ μΌλΆ€λ‘œ μ‚¬μš©ν•  κΈ°λ³Έ "FROM 슀크래치"이미지λ₯Ό λ§Œλ“€λ €κ³ ν•©λ‹ˆλ‹€. 일뢀 λ…Όλ¦¬λŠ” 11 개 λͺ¨λ‘μ—μ„œ λ™μΌν•˜κ³  μ—¬κΈ°μ—λŠ” ν™˜κ²½ λ³€μˆ˜κ°€ ν¬ν•¨λ˜μ–΄ 있기 λ•Œλ¬Έμž…λ‹ˆλ‹€. λ”°λΌμ„œ 각 이미지 λ‚΄μ—μ„œ μ„€μ •ν•΄μ•Όν•˜λŠ” ν™˜κ²½ λ³€μˆ˜κ°€ 있으며 λ™μΌν•œ 논리가 λ‹€λ₯Έ λͺ¨λ“  이미지에 볡제 될 ν•„μš”κ°€ 없도둝 κΈ°λ³Έ 이미지 λ‚΄μ—μ„œ μ΄λŸ¬ν•œ λ³€μˆ˜λ₯Ό μ„€μ •ν•˜λ €κ³ ν•©λ‹ˆλ‹€.

ARG 의 @ DMaxfield-BDS λ²”μœ„λŠ” λ³€κ²½λ˜μ§€ μ•Šμ§€λ§Œ "FROM 슀크래치"κΈ°λ³Έ 이미지λ₯Ό μƒμ„±ν•˜λŠ” λ³„λ„μ˜ λΉŒλ“œ λŒ€μƒμ„ κ³ λ €ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 그것을 λ ˆμ§€μŠ€νŠΈλ¦¬λ‘œ ν‘Έμ‹œν•˜κ³  λ‹€λ₯Έ 이미지에 λŒ€ν•΄ μ‚¬μš©ν•˜μ‹­μ‹œμ˜€.

FROM scratch AS scratch-base
ENV foo=bar
ENV bar=baz

λΉŒλ“œν•˜κ³  (λ‚΄λΆ€) λ ˆμ§€μŠ€νŠΈλ¦¬λ‘œ ν‘Έμ‹œν•˜λ©΄ 11 개의 κΈ°λ³Έ 이미지가이λ₯Ό 기본으둜 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

FROM scratch-base
RUN your stuff

λ‹€λ₯Έ μ‚¬μš© 사둀에 λ§žλŠ” EXPORT/IMPORT λ₯Ό κ°–λŠ” 또 λ‹€λ₯Έ μ œμ•ˆμ΄ μžˆμŠ΅λ‹ˆλ‹€. https://github.com/moby/moby/issues/32100

λΏ‘ 빡뀨

λ‹Ήμ‹ μ˜ 응닡을 μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€. λ‚΄κ°€ μ§€μ ν•˜μ§€ μ•Šμ€ ν•œ κ°€μ§€λŠ” λ‹€λ₯Έ 11 개의 이미지가 λͺ¨λ‘ λ‹€λ₯Έ κΈ°λ³Έ 이미지 (python, npm, postgres, openjdk λ“±)λ₯Ό 가지고 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. κ·Έλž˜μ„œ μ œκ°€ μ›ν•˜λŠ” 것은 λ‹€μŒκ³Ό 같이 νšŒμ‚¬ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ μ‚¬μš©ν•˜λŠ” ν•„μš”ν•œ ν™˜κ²½ λ³€μˆ˜λ₯Ό μ„€μ •ν•˜λŠ” 것을 ν¬ν•¨ν•˜μ—¬ λͺ¨λ“  일반적인 μ„€μ • / μ€€λΉ„λ₯Ό ν•˜λ‚˜μ˜ κΈ°λ³Έ 이미지에 λ„£λŠ” κ²ƒμž…λ‹ˆλ‹€.

FROM scratch AS scratch-base
ARG JAR_DIR='/Input/jars/'
ENV JAR_DOWNLOAD_DIR=$JAR_DIR

λ‚΄ λ‚΄λΆ€ λ ˆμ§€μŠ€νŠΈλ¦¬λ‘œ ν‘Έμ‹œν•©λ‹ˆλ‹€. 그런 λ‹€μŒ λ‹€λ₯Έ 11 개 이미지 쀑 ν•˜λ‚˜μ˜ μ˜ˆλŠ” λ‹€μŒμ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.

FROM scratch-base AS scratch-base
FROM openjdk:8-jdk
COPY --from=scratch-base $JAR_DOWNLOAD_DIR .
RUN <stuff that also uses the JAR_DOWNLOAD_DIR environment variable>

첫 번째 이미지에 μ„€μ •λœ ν™˜κ²½ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€λ©΄ λ‹€λ₯Έ 11 개의 이미지 κ°κ°μ—μ„œ μ΄λŸ¬ν•œ λ™μΌν•œ 섀정을 ꡬ성 ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. 이것은 λ‚˜μ—κ²Œ ν•˜λ‚˜μ˜ ꡬ성 지점을 ν—ˆμš©ν•˜κ³  더 λ‚˜μ€ μžλ™ν™”λ₯Ό ν—ˆμš©ν•©λ‹ˆλ‹€.

μ–΄λ–»κ²Œ 이런 μΌμ„ν•΄μ•Όν•©λ‹ˆκΉŒ?

RUN COMMIT_HASH = $ (git rev-parse --short HEAD)

후속 RUN λ‹¨κ³„μ—μ„œ COMMIT_HASH λ³€μˆ˜λ₯Ό μ–΄λ–»κ²Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆκΉŒ? λ³€μˆ˜λ₯Ό μ •μ˜ν•˜κ³  ν•œ λ²ˆμ— λͺ¨λ‘ μ‚¬μš©ν•΄μ•Όν•©λ‹ˆκΉŒ?

제 생각에이 λ””μžμΈμ€ 맀우 μ œν•œμ μž…λ‹ˆλ‹€. μ•„λ§ˆλ„ λ‹€μŒκ³Ό 같이 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

RUN COMMIT_HASH = $ (git rev-parse --short HEAD) AS commit-hash
ARG --from = commit-hash COMMIT_HASH
RUN echo $ {COMMIT_HASH}

@ dnk8n 이것은 λ‚΄κ°€ 그것을 ν•΄κ²°ν•˜κΈ° μœ„ν•΄ν•˜λŠ” μΌμž…λ‹ˆλ‹€.

λΉŒλ“œ λ‹¨κ³„μ—μ„œ λ‹€μŒμ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.

RUN git rev-parse HEAD > commit_hash

그런 λ‹€μŒ λ‹€λ₯Έ λ‹¨κ³„μ—μ„œ 데이터와 ν•¨κ»˜ νŒŒμΌμ„ λ³΅μ‚¬ν•˜κ³ μ΄λ₯Ό μ‚¬μš©ν•˜λŠ” 앱을 μ‹€ν–‰ν•˜κΈ° 전에 ν™˜κ²½ λ³€μˆ˜λ₯Ό μ„€μ •ν•©λ‹ˆλ‹€.

COPY --from=builder /<build_folder>/commit_hash /<other_stage_folder>/commit_hash

CMD export COMMIT_HASH=$(cat /<other_stage_folder>/commit_hash); java -jar myApp.jar

ARGλ₯Ό μ„€μ •ν•˜κΈ° μœ„ν•΄ μœ μ‚¬ν•œ μž‘μ—…μ„ μˆ˜ν–‰ ν•  수 μžˆμ–΄μ•Όν•©λ‹ˆλ‹€.

μ΅œμ†Œν•œ λ‹€λ₯Έ 단계 / μ΄λ―Έμ§€μ˜ BAR λ³€μˆ˜λ₯Ό ν˜„μž¬ λΉŒλ“œ λ²”μœ„λ‘œ λ³΅μ‚¬ν•˜λ €λ©΄ 이와 같은 μž‘μ—…μ„ μˆ˜ν–‰ ν•  수 μžˆμ–΄μ•Όν•©λ‹ˆλ‹€.

ENV --from=stage1 FOO=$BAR

이것은 ν™˜κ²½ λ³€μˆ˜μ— μ€‘μš”ν•œ 메타 λ°μ΄ν„°κ°€μžˆμ„ 수 있기 λ•Œλ¬Έμ— μ™ΈλΆ€ 이미지λ₯Ό λ¬΄λŒ€λ‘œ μ‚¬μš©ν•˜λŠ” 것을 κ³ λ €ν•  λ•Œ λ”μš± μ€‘μš”ν•©λ‹ˆλ‹€.

ENV --from=nginx:latest FOO=$BAR

이 νŒ¨ν„΄μ„ μ‚¬μš©ν•˜μ—¬ 각 λ‹¨κ³„μ—μ„œ ν™˜κ²½μ„ νŒŒμΌμ— μ €μž₯ν•˜μ—¬ ν•΄κ²° μ€‘μž…λ‹ˆλ‹€.

FROM base1:version1 AS BUILDER1
WORKDIR /build
RUN env | sort > env.BUILDER1

FROM base2:version2 AS BUILDER2
WORKDIR /build
RUN env | sort > env.BUILDER2

FROM finalbase:version AS FINAL
WORKDIR /build
ENV LANG=C.UTF-8
COPY --from=BUILDER1 /build/env.BUILDER1 .
COPY --from=BUILDER2 /build/env.BUILDER2 .
# Use ". ./env.BUILDER" instead of "source" if /bin/sh is true-POSIX
RUN set -eux ; \
        source ./env.BUILDER1 ; \
        source ./env.BUILDER2 ; \
        env | sort

docker inspect μ‹€ν–‰ν•  λ•Œ λ³Ό 수 μžˆλ„λ‘ 'docker'에 λ§ˆμ§€λ§‰μœΌλ‘œ 'μ €μž₯'ν•  μˆ˜μžˆλŠ” 방법은 ν™•μ‹€ν•˜μ§€ μ•Šμ§€λ§Œ 예λ₯Ό λ“€μ–΄ / etc / profile에 λ“€μ–΄κ°ˆ 수 μžˆμŠ΅λ‹ˆλ‹€.

image

λ§ˆμ§€λ§‰ λŒ“κΈ€μ΄ λ„ˆλ¬΄ μ‹ μ„ ν•˜λ‹€λŠ” 것을 λ³΄μ•˜μ„ λ•Œ μ–Όλ§ˆλ‚˜ λ§Žμ€ κ°œλ°œμžκ°€ dockerfile이면의 λ””μžμΈ 결정에 μ˜λ¬Έμ„ μ œκΈ°ν•˜λŠ”μ§€ μ—Ώλ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. λΆ„λͺ…νžˆ "DRY"λŠ” μˆ™λ ¨ 된 기술이 μ•„λ‹ˆ μ—ˆμŠ΅λ‹ˆλ‹€. μ‹œλ„ν•˜κ³  μ‹Άλ‹€λ©΄ λ‹€λ₯Έ λ ˆμ΄μ–΄λ₯Ό μΆ”κ°€ν•˜κ³  dockerfiles ν…œν”Œλ¦Ώμ„ μ‹œμž‘ν•˜μ‹­μ‹œμ˜€ ...

μ†”μ§νžˆ λ§ν•΄μ„œ λ‚˜λŠ” 이것에 λŒ€ν•΄ 맀우 λ†€λžμŠ΅λ‹ˆλ‹€. "global arg"λŠ” μ €μ—κ²Œ νš¨κ³Όκ°€μ—†λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€. λΉŒλ“œ 인수λ₯Ό λ‹€λ₯Έ 것보닀 λ¨Όμ € 맨 μœ„λ‘œ μ΄λ™ν•˜λ©΄ FROM 이후에 λ‹€μŒ 단계에 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 것과 κ°™μŠ΅λ‹ˆλ‹€.

νŽΈμ§‘ : λ‚˜λŠ” μ–΄μ¨Œλ“  각 FROM 후에 κ°’μ΄μ—†λŠ” ARG 라인을 λ°˜λ³΅ν•΄μ•Όν•œλ‹€λŠ” 것을 μ•Œμ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€. μž‘λ™ν•˜μ§€λ§Œ 이상적이지 μ•ŠμŠ΅λ‹ˆλ‹€.

λ‹€λ₯Έ λ‹¨κ³„μ—μ„œ ν™˜κ²½ λ³€μˆ˜λ₯Ό λͺ…μ‹œ 적으둜 볡사 (κ°€μ Έ 였기)ν•˜λŠ” 방법은 ν•„μˆ˜μž…λ‹ˆλ‹€. μœ νš¨ν•œ μ‚¬μš© 사둀가 μžˆμŠ΅λ‹ˆλ‹€.
λ‹€μŒμ€ κ°„λ‹¨ν•œ μ˜ˆμž…λ‹ˆλ‹€.

FROM node:lts-alpine AS node
FROM php:7-fpm-alpine AS php

# Here goes some build instructions for PHP image, then

# Install nodejs, npm, yarn
COPY --from=node /usr/local/bin/node /usr/local/bin/node
COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules
COPY --from=node /opt /opt

# Create symlinks to npm, yarn binaries
RUN \
    ln -s "/usr/local/lib/node_modules/npm/bin/npm-cli.js" /usr/local/bin/npm \
    && ln -s "/usr/local/lib/node_modules/npm/bin/npx-cli.js" /usr/local/bin/npx \
    && ln -s /opt/yarn-v1.??.?/bin/yarn /usr/local/bin/yarn \
    && ln -s /opt/yarn-v1.??.?/bin/yarnpkg /usr/local/bin/yarnpkg

# Some other instructions

이제 ν™˜κ²½ λ³€μˆ˜μ˜ λ…Έλ“œ 이미지 ( YARN_VERSION )에 μ •μ˜ 된 μ–€ 버전을 μ–΄λ–»κ²Œ μ•Œ 수 μžˆμŠ΅λ‹ˆκΉŒ?

닀단계 λΉŒλ“œλŠ” CI νŒŒμ΄ν”„ 라인의 μ—„μ²­λ‚œ 이점과 ν•¨κ»˜ μˆ˜μš©λ©λ‹ˆλ‹€. "ν™˜κ²½ 상속"κ³Ό 같은 κΈ°λŠ₯은 λ‹€λ₯Έ μˆ˜μ€€μ˜ μœ μ§€ 관리 및 κΈ°λŠ₯ ν˜„λͺ…ν•¨μœΌλ‘œ λ°€μ–΄ λ„£μŠ΅λ‹ˆλ‹€.

ν™˜κ²½ λ³€μˆ˜λ₯Ό 많이 μ‚¬μš©ν•˜λŠ” μ•½ 5 개의 λ ˆμ΄μ–΄κ°€ 있으며 λͺ¨λ“  μ—…λ°μ΄νŠΈλŠ” μ•…λͺ½μž…λ‹ˆλ‹€. 밝은면 (?), μƒˆλ‘œμš΄ λ¬΄λŒ€λ₯Ό μ†Œκ°œν•˜κΈ° 전에 차라리 두 번 μƒκ°ν•©λ‹ˆλ‹€.

ν˜„μž¬ ARG κ΅¬ν˜„μ€ λͺ‡ 가지 ν₯미둜운 λ™μž‘μ„ μ œκ³΅ν•©λ‹ˆλ‹€.

FROM python
ARG X=os    # or ENV, the same  
RUN echo import ${X:-sys}   # Proof that the syntax works with default SHELL
SHELL ["python", "-c"]
RUN import os
RUN import ${X}  # Fails
RUN import ${X:-sys}  # Fails too, but this is a documented syntax (for ENV)

λ˜λŠ”

FROM alpine
ARG X=ab.cd
RUN echo ${X%.*}  # it's ok but it looks like magic 
WORKDIR ${X%.*}  # Fails here 

μ΄λŠ” ARGκ°€ ν…œν”Œλ¦Ώμ΄ μ•„λ‹Œ 단계별 ν™˜κ²½ λ³€μˆ˜λΌλŠ” 사싀과 관련이 μžˆμŠ΅λ‹ˆλ‹€.

λ‚˜λŠ” λ‹Ήμ‹  (그리고 λ‚˜)이 μ‹€μƒν™œμ—μ„œ 그것을 κ²°μ½” 보지 λͺ»ν–ˆλ‹€λŠ” 것을 μ•Œκ³  μžˆμŠ΅λ‹ˆλ‹€ (μ•„λ§ˆλ„ λ¬Έμžμ—΄ μ‘°μž‘ ...).
κ·ΈλŸ¬λ‚˜ 이것은 도컀 ꡬ문이 언더 λ ˆμ΄μ–΄ μ‰˜ ꡬ문을 κΈ°λ°˜μœΌλ‘œν•œλ‹€λŠ” 사싀을 κ°•μ‘°ν•©λ‹ˆλ‹€. μ΄λŠ” λ¬Έμ„œλ₯Ό κ±°μ§“λ§λ‘œ λ§Œλ“­λ‹ˆλ‹€. (https://docs.docker.com/engine/reference/builder/#environment-replacement 및 λ°˜λŒ€ 예제 " RUN import ${X:-sys} "μ°Έμ‘°)

λ ˆκ±°μ‹œ 'make'처럼 λͺ…령을 μ‹€ν–‰ν•˜κΈ° 전에 RUN이 ARGλ₯Ό ν•΄μ„ν•˜μ§€ μ•ŠλŠ” μ΄μœ λŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ?

$ cat Makefile
SHELL=python
X=os
test:
    import os
    import ${X}
$ make test
import os
import os

24 μ‹œκ°„μ΄ λλ‚¬μŠ΅λ‹ˆλ‹€ =)

_ κ²½κ³  _이 μ†”λ£¨μ…˜μ€ μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

첫 번째 λ‹¨κ³„μ˜ νŒŒμΌμ— env varλ₯Ό μ“°κ³  두 번째 λ‹¨κ³„μ˜ 파일 ν•˜λ‚˜λ₯Ό 볡사 ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ? 기타? μ΄λ ‡κ²Œ :

FROM golang:1.14 as cm_base
ARG commit_id
RUN echo "$commit_id" > /tmp/env.json
FROM golang:1.14
COPY --from=cm_base "/tmp/env.json" "/tmp/env.json"
ENV cm_cc_commit_id="$(cat /tmp/env.json)"

μž‘λ™ν•˜μ§€ μ•ŠλŠ” 것을 μ œμ™Έν•˜κ³ λŠ” cm_cc_commit_id λŠ” λ¦¬ν„°λŸ΄ $(cat /tmp/env.json) κ°€λ˜κ³  ν›„μžμ˜ ν‘œν˜„μ‹μ€ ν‰κ°€λ˜μ§€ μ•Šκ³  λ¦¬ν„°λŸ΄λ‘œ μœ μ§€λ©λ‹ˆλ‹€. κ·Έλž˜μ„œ 동적 ν™˜κ²½ λ³€μˆ˜λ₯Ό μ„€μ •ν•˜λŠ” 것이 λΆˆκ°€λŠ₯ ν•΄ λ³΄μž…λ‹ˆκΉŒ?

κ·ΈλŸ¬λ‚˜ μž‘λ™ν•˜λŠ” 것은 νŒŒμΌμ— μ“°κ³  μ§„μž… 점을 bash 파일둜 λ§Œλ“  λ‹€μŒ λ‹€μŒμ„ μˆ˜ν–‰ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

#!/usr/bin/env bash
echo "the docker entrypoint args:" "$@"
export cm_cc_commit_id="$(cat /tmp/env.json)"
"$@"

λ‹€μŒκ³Ό 같이 μƒκ°ν•˜μ‹­μ‹œμ˜€.

Dockerfileμ—λŠ” μ „μ—­ ARG λ₯Ό ν†΅ν•œ 경우λ₯Ό μ œμ™Έν•˜κ³ λŠ” λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜λŠ” μˆ˜λ‹¨μ΄ μ—†μŠ΅λ‹ˆλ‹€. μ΄λŠ” 캐싱에 영ν–₯을 미치기 λ•Œλ¬Έμ— 각 단계에 μžλ™μœΌλ‘œ μ „νŒŒλ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
λΉŒλ”λŠ” 더 λ˜‘λ˜‘ ν•  수 있으며 νŠΉμ • λ‹¨κ³„μ—μ„œ ARG λ₯Ό μ‚¬μš© ν•˜λ €λŠ”μ§€ μ—¬λΆ€λ₯Ό νŒλ‹¨ν•˜κ³  ν—ˆμš© ν•  수 μžˆμ§€λ§Œ λ¦¬ν„°λŸ΄μ„ μ›ν•˜λŠ”μ§€ μ—¬λΆ€λ₯Ό μΆ”μΈ‘ν•΄μ•Όν•©λ‹ˆλ‹€.

λ”°λΌμ„œ 예, μ „μ—­ ARG λ₯Ό μ‚¬μš©ν•˜λ €λŠ” 각 λ‹¨κ³„λ‘œ λͺ…μ‹œ 적으둜 κ°€μ Έμ™€μ•Όν•©λ‹ˆλ‹€. μ•„λ§ˆλ„ λΉŒλ” λ˜λŠ” λ¦°ν„°κ°€ ARG λ₯Ό μ‚¬μš©ν•˜λ €κ³ ν•˜λŠ” κ²ƒμ²˜λŸΌ λ³΄μ΄λŠ” 경우 κ²½κ³ λ₯Ό κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€ ARG μž…λ‹ˆλ‹€.
이것은 섀계에 μ˜ν•΄ κΉ¨μ§€λŠ” 것이 μ•„λ‹ˆλΌ 더 적은 μ½”λ“œ 쀄에 λŒ€ν•΄ 졜적의 캐싱을 μ„ νƒν•˜λŠ” λͺ…μ‹œμ μΈ μ„ νƒμž…λ‹ˆλ‹€.

μ „μ—­ ARG 의 μ‚¬μš©μ΄ μ²˜μŒμ—λŠ” ν˜Όλž€μŠ€λŸ¬μ›Œν•œλ‹€λŠ” 것은 ν™•μ‹€νžˆ μ΄ν•΄λ©λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰