Tìm hiểu về Docker - Phần 4 - Tạo image từ Dockerfile

Mở đầu

Ở các phần trước mình đã giới thiệu tổng quan Docker Engine và kiến trúc của Docker, cũng như chạy một container đầu tiên với các image có sẵn. Ở phần này mình sẽ viết hướng dẫn tạo image bằng Dockerfile

1. Dockerfile là gì ?

  • Dockerfile là một file dạng text không có extension, và tên bắt buộc phải là Dockerfile

  • Dockerfile là một file kịch bản sử dụng để tạo mới một image

2. Cấu trúc một Dockerfile

Đây là cấu trúc một Dockerfile của ứng dụng Wordpress

FROM php:7.1-apache

# install the PHP extensions we need
RUN set -ex; \
	\
	savedAptMark="$(apt-mark showmanual)"; \
	\
	apt-get update; \
	apt-get install -y --no-install-recommends \
		libjpeg-dev \
		libpng-dev \
	; \
	\
	docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr; \
	docker-php-ext-install gd mysqli opcache zip; \
	\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
	apt-mark auto '.*' > /dev/null; \
	apt-mark manual $savedAptMark; \
	ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \
		| awk '/=>/ { print $3 }' \
		| sort -u \
		| xargs -r dpkg-query -S \
		| cut -d: -f1 \
		| sort -u \
		| xargs -rt apt-mark manual; \
	\
	apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
	rm -rf /var/lib/apt/lists/*

# set recommended PHP.ini settings
# see https://secure.php.net/manual/en/opcache.installation.php
RUN { \
		echo 'opcache.memory_consumption=128'; \
		echo 'opcache.interned_strings_buffer=8'; \
		echo 'opcache.max_accelerated_files=4000'; \
		echo 'opcache.revalidate_freq=2'; \
		echo 'opcache.fast_shutdown=1'; \
		echo 'opcache.enable_cli=1'; \
	} > /usr/local/etc/php/conf.d/opcache-recommended.ini

RUN a2enmod rewrite expires

VOLUME /var/www/html

ENV WORDPRESS_VERSION 5.0.3
ENV WORDPRESS_SHA1 f9a4b482288b5be7a71e9f3dc9b5b0c1f881102b

RUN set -ex; \
	curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz"; \
	echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c -; \
# upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress
	tar -xzf wordpress.tar.gz -C /usr/src/; \
	rm wordpress.tar.gz; \
	chown -R www-data:www-data /usr/src/wordpress

COPY docker-entrypoint.sh /usr/local/bin/

ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["apache2-foreground"]

3. Các command cơ bản trong Dockerfile

FROM

FROM centos:centos7

FROM chỉ định rằng image build này sẽ base trên image gốc nào

LABEL

LABEL "image-type"="huy-test"
LABEL "image-type1"="huy-test1"
LABEL "image-type2"="huy-test2"

LABEL: Chỉ định label metadata của image. Để xem được các label này sử dụng câu lệnh docker inspect <IMAGE ID>

MAINTAINER

MAINTAINER huytm

MAINTERNER là author (tác giả) build image đó.

RUN

RUN yum update -y

RUN thực hiện một câu lệnh Linux. Tùy vào image gốc mà có các câu lệnh tương ứng (ví dụ Ubuntu sẽ là RUN apt-get update -y)

COPY

COPY start.sh /start.sh

COPY Copy một file từ Dockerhost vào image trong quá trình build image

ENV

ENV source /var/www/html/
COPY index.html ${source}

ENV là biến môi trường sử dụng trong quá trình build image.

ENV chỉ có thể được sử dụng trong các command sau:

  • ADD
  • COPY
  • ENV
  • EXPOSE
  • FROM
  • LABEL
  • STOPSIGNAL
  • USER
  • VOLUME
  • WORKDIR

CMD

CMD ["./start.sh"]

CMD dùng để truyền một Linux command khi khởi tạo container từ image

VOLUME

VOLUME ["/etc/http"]

VOLUME Tạo một volume nằm trong folder /var/lib/docker/volumes của docker host và mount với folder chẳng hạn /etc/http khi khởi chạy container

EXPOSE

EXPOSE 80 443

EXPOSE Chỉ định các port sẽ Listen trong container khi khởi chạy container từ image

4. Tạo images httpd với Dockerfile

Yêu cầu:

  • VPS đã cài đặt Docker, nếu bạn chưa cài đặt thì cài đặt theo bài viết này
  • Giả định môi trường lý tưởng, các câu lệnh sau đều chạy dưới quyền root

a. Tạo một folder làm việc với Dockerfile

cd ~
mkdir build_image && cd build_image

b. Tạo Dockerfile để build image

touch Dockerfile

Lưu ý: Filename phải là Dockerfile và không có phần mở rộng

c. Nội dung Dockerfile như sau:

FROM centos:centos7

LABEL "image-type"="huy-test"
MAINTAINER huytm

RUN yum update -y
RUN yum install httpd -y

ENV source /var/www/html/

VOLUME ["/var/log/httpd"]

COPY index.html ${source}
COPY start.sh /start.sh

RUN chmod +x /start.sh
CMD ["/start.sh"]

EXPOSE 80

Giải thích:

  • FROM centos:centos7 : Build image dựa trên image gốc là centos 7.

  • RUN yum update -yRUN yum install httpd -y : Thực hiện các command của centos để update và cài đặt httpd

  • LABEL “image-type”=”huy-test” : Metadata của image có thể có hoặc không.

  • MAINTAINER huytm : Tác giả viết Dockerfile để build image có thể có hoặc không.

  • ENV source /var/www/html/ : Khai báo một biến môi trường tên là source và có giá trị là /var/www/html/. Biến này sẽ được sử dụng ở bước COPY index.html ${source}

  • COPY index.html ${source} : Copy file index.html từ Dockerhost vào đường dẫn biến - được khai báo ở bước trên.

  • COPY start.sh /start.sh : Copy một bash script file vào đường dẫn / để thực hiện một số Linux command khi khởi tạo container từ image này.

  • RUN chmod +x /start.sh : Cho phép quyền thực thi đối với script vừa copy từ bước trên.

  • CMD [“/start.sh”] : Thực thi script khi khởi chạy container từ image này.

  • EXPOSE 80 : Chỉ ra rằng container khi khởi chạy từ image này sẽ LISTEN port 80

  • VOLUME [“/var/log/httpd”] : Chỉ định một phân vùng trên Docker host mount với container khi chạy. Ở đây mình mount theo dạng volume (Có ba kiểu volume, mình sẽ nói trong các bài viết sau). Mount folder /var/log/httpd của container với volume nằm tại /var/lib/portal/volume/ của Docker host

d. Tạo các file cần thiết bổ trợ cho Dockerfile

Vì ở trên mình có sử dụng COPY để COPY các file script start.sh và file source code index.html nên mình sẽ tạo tiếp hai file này.

cat <<EOF > start.sh
	#!/bin/bash
	rm -rf /run/httpd/* /tmp/httpd*
	exec /usr/sbin/apachectl -DFOREGROUND
EOF
echo "<h1>Hello World</h1>" > index.html

e. Tạo image từ Dockerfile

docker build -t huytm/centos7-httpd .

Đây là toàn bộ log của quá trình build

Sending build context to Docker daemon  4.096kB
Step 1/12 : FROM centos:centos7
 ---> 1e1148e4cc2c
Step 2/12 : LABEL "image-type"="huy-test"
 ---> Running in 220997b26a05
Removing intermediate container 220997b26a05
 ---> 767cb6c0db64
Step 3/12 : MAINTAINER huytm
 ---> Running in 87547a35ac1f
Removing intermediate container 87547a35ac1f
 ---> 1333a9d9ceed
Step 4/12 : RUN yum update -y
 ---> Running in 66eb8c88d680
Loaded plugins: fastestmirror, ovl
Determining fastest mirrors
 * base: centos-hn.viettelidc.com.vn
 * extras: centos-hn.viettelidc.com.vn
 * updates: centos-hn.viettelidc.com.vn
Resolving Dependencies
--> Running transaction check
---> Package bind-license.noarch 32:9.9.4-72.el7 will be updated
---> Package bind-license.noarch 32:9.9.4-73.el7_6 will be an update
---> Package device-mapper.x86_64 7:1.02.149-10.el7_6.2 will be updated
---> Package device-mapper.x86_64 7:1.02.149-10.el7_6.3 will be an update
---> Package device-mapper-libs.x86_64 7:1.02.149-10.el7_6.2 will be updated
---> Package device-mapper-libs.x86_64 7:1.02.149-10.el7_6.3 will be an update
---> Package glibc.x86_64 0:2.17-260.el7 will be updated
---> Package glibc.x86_64 0:2.17-260.el7_6.3 will be an update
---> Package glibc-common.x86_64 0:2.17-260.el7 will be updated
---> Package glibc-common.x86_64 0:2.17-260.el7_6.3 will be an update
---> Package krb5-libs.x86_64 0:1.15.1-34.el7 will be updated
---> Package krb5-libs.x86_64 0:1.15.1-37.el7_6 will be an update
---> Package nss.x86_64 0:3.36.0-7.el7_5 will be updated
---> Package nss.x86_64 0:3.36.0-7.1.el7_6 will be an update
---> Package nss-sysinit.x86_64 0:3.36.0-7.el7_5 will be updated
---> Package nss-sysinit.x86_64 0:3.36.0-7.1.el7_6 will be an update
---> Package nss-tools.x86_64 0:3.36.0-7.el7_5 will be updated
---> Package nss-tools.x86_64 0:3.36.0-7.1.el7_6 will be an update
---> Package nss-util.x86_64 0:3.36.0-1.el7_5 will be updated
---> Package nss-util.x86_64 0:3.36.0-1.1.el7_6 will be an update
---> Package openldap.x86_64 0:2.4.44-20.el7 will be updated
---> Package openldap.x86_64 0:2.4.44-21.el7_6 will be an update
---> Package systemd.x86_64 0:219-62.el7 will be updated
---> Package systemd.x86_64 0:219-62.el7_6.3 will be an update
---> Package systemd-libs.x86_64 0:219-62.el7 will be updated
---> Package systemd-libs.x86_64 0:219-62.el7_6.3 will be an update
---> Package tzdata.noarch 0:2018g-1.el7 will be updated
---> Package tzdata.noarch 0:2018i-1.el7 will be an update
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
 Package                Arch       Version                    Repository   Size
================================================================================
Updating:
 bind-license           noarch     32:9.9.4-73.el7_6          updates      87 k
 device-mapper          x86_64     7:1.02.149-10.el7_6.3      updates     292 k
 device-mapper-libs     x86_64     7:1.02.149-10.el7_6.3      updates     320 k
 glibc                  x86_64     2.17-260.el7_6.3           updates     3.7 M
 glibc-common           x86_64     2.17-260.el7_6.3           updates      12 M
 krb5-libs              x86_64     1.15.1-37.el7_6            updates     803 k
 nss                    x86_64     3.36.0-7.1.el7_6           updates     835 k
 nss-sysinit            x86_64     3.36.0-7.1.el7_6           updates      62 k
 nss-tools              x86_64     3.36.0-7.1.el7_6           updates     515 k
 nss-util               x86_64     3.36.0-1.1.el7_6           updates      78 k
 openldap               x86_64     2.4.44-21.el7_6            updates     356 k
 systemd                x86_64     219-62.el7_6.3             updates     5.1 M
 systemd-libs           x86_64     219-62.el7_6.3             updates     406 k
 tzdata                 noarch     2018i-1.el7                updates     490 k

Transaction Summary
================================================================================
Upgrade  14 Packages

Total download size: 24 M
Downloading packages:
Delta RPMs disabled because /usr/bin/applydeltarpm not installed.
warning: /var/cache/yum/x86_64/7/updates/packages/bind-license-9.9.4-73.el7_6.noarch.rpm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5: NOKEY
Public key for bind-license-9.9.4-73.el7_6.noarch.rpm is not installed
--------------------------------------------------------------------------------
Total                                              5.4 MB/s |  24 MB  00:04
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
Importing GPG key 0xF4A80EB5:
 Userid     : "CentOS-7 Key (CentOS 7 Official Signing Key) <security@centos.org>"
 Fingerprint: 6341 ab27 53d7 8a78 a7c2 7bb1 24c6 a8a7 f4a8 0eb5
 Package    : centos-release-7-6.1810.2.el7.centos.x86_64 (@CentOS)
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Updating   : tzdata-2018i-1.el7.noarch                                   1/28
  Updating   : glibc-2.17-260.el7_6.3.x86_64                               2/28
  Updating   : glibc-common-2.17-260.el7_6.3.x86_64                        3/28
  Updating   : nss-util-3.36.0-1.1.el7_6.x86_64                            4/28
  Updating   : systemd-libs-219-62.el7_6.3.x86_64                          5/28
  Updating   : systemd-219-62.el7_6.3.x86_64                               6/28
Failed to get D-Bus connection: Operation not permitted
  Updating   : 7:device-mapper-1.02.149-10.el7_6.3.x86_64                  7/28
  Updating   : 7:device-mapper-libs-1.02.149-10.el7_6.3.x86_64             8/28
  Updating   : nss-sysinit-3.36.0-7.1.el7_6.x86_64                         9/28
  Updating   : nss-3.36.0-7.1.el7_6.x86_64                                10/28
  Updating   : nss-tools-3.36.0-7.1.el7_6.x86_64                          11/28
  Updating   : openldap-2.4.44-21.el7_6.x86_64                            12/28
  Updating   : krb5-libs-1.15.1-37.el7_6.x86_64                           13/28
  Updating   : 32:bind-license-9.9.4-73.el7_6.noarch                      14/28
  Cleanup    : 32:bind-license-9.9.4-72.el7.noarch                        15/28
  Cleanup    : openldap-2.4.44-20.el7.x86_64                              16/28
  Cleanup    : nss-tools-3.36.0-7.el7_5.x86_64                            17/28
  Cleanup    : nss-sysinit-3.36.0-7.el7_5.x86_64                          18/28
  Cleanup    : nss-3.36.0-7.el7_5.x86_64                                  19/28
  Cleanup    : 7:device-mapper-1.02.149-10.el7_6.2.x86_64                 20/28
  Cleanup    : 7:device-mapper-libs-1.02.149-10.el7_6.2.x86_64            21/28
  Cleanup    : systemd-219-62.el7.x86_64                                  22/28
  Cleanup    : systemd-libs-219-62.el7.x86_64                             23/28
  Cleanup    : nss-util-3.36.0-1.el7_5.x86_64                             24/28
  Cleanup    : krb5-libs-1.15.1-34.el7.x86_64                             25/28
  Cleanup    : glibc-common-2.17-260.el7.x86_64                           26/28
  Cleanup    : glibc-2.17-260.el7.x86_64                                  27/28
  Cleanup    : tzdata-2018g-1.el7.noarch                                  28/28
  Verifying  : systemd-libs-219-62.el7_6.3.x86_64                          1/28
  Verifying  : nss-tools-3.36.0-7.1.el7_6.x86_64                           2/28
  Verifying  : systemd-219-62.el7_6.3.x86_64                               3/28
  Verifying  : 32:bind-license-9.9.4-73.el7_6.noarch                       4/28
  Verifying  : nss-util-3.36.0-1.1.el7_6.x86_64                            5/28
  Verifying  : 7:device-mapper-libs-1.02.149-10.el7_6.3.x86_64             6/28
  Verifying  : krb5-libs-1.15.1-37.el7_6.x86_64                            7/28
  Verifying  : nss-sysinit-3.36.0-7.1.el7_6.x86_64                         8/28
  Verifying  : nss-3.36.0-7.1.el7_6.x86_64                                 9/28
  Verifying  : tzdata-2018i-1.el7.noarch                                  10/28
  Verifying  : glibc-2.17-260.el7_6.3.x86_64                              11/28
  Verifying  : glibc-common-2.17-260.el7_6.3.x86_64                       12/28
  Verifying  : 7:device-mapper-1.02.149-10.el7_6.3.x86_64                 13/28
  Verifying  : openldap-2.4.44-21.el7_6.x86_64                            14/28
  Verifying  : nss-3.36.0-7.el7_5.x86_64                                  15/28
  Verifying  : openldap-2.4.44-20.el7.x86_64                              16/28
  Verifying  : nss-util-3.36.0-1.el7_5.x86_64                             17/28
  Verifying  : 7:device-mapper-1.02.149-10.el7_6.2.x86_64                 18/28
  Verifying  : systemd-libs-219-62.el7.x86_64                             19/28
  Verifying  : glibc-common-2.17-260.el7.x86_64                           20/28
  Verifying  : systemd-219-62.el7.x86_64                                  21/28
  Verifying  : nss-tools-3.36.0-7.el7_5.x86_64                            22/28
  Verifying  : glibc-2.17-260.el7.x86_64                                  23/28
  Verifying  : krb5-libs-1.15.1-34.el7.x86_64                             24/28
  Verifying  : 7:device-mapper-libs-1.02.149-10.el7_6.2.x86_64            25/28
  Verifying  : 32:bind-license-9.9.4-72.el7.noarch                        26/28
  Verifying  : nss-sysinit-3.36.0-7.el7_5.x86_64                          27/28
  Verifying  : tzdata-2018g-1.el7.noarch                                  28/28

Updated:
  bind-license.noarch 32:9.9.4-73.el7_6
  device-mapper.x86_64 7:1.02.149-10.el7_6.3
  device-mapper-libs.x86_64 7:1.02.149-10.el7_6.3
  glibc.x86_64 0:2.17-260.el7_6.3
  glibc-common.x86_64 0:2.17-260.el7_6.3
  krb5-libs.x86_64 0:1.15.1-37.el7_6
  nss.x86_64 0:3.36.0-7.1.el7_6
  nss-sysinit.x86_64 0:3.36.0-7.1.el7_6
  nss-tools.x86_64 0:3.36.0-7.1.el7_6
  nss-util.x86_64 0:3.36.0-1.1.el7_6
  openldap.x86_64 0:2.4.44-21.el7_6
  systemd.x86_64 0:219-62.el7_6.3
  systemd-libs.x86_64 0:219-62.el7_6.3
  tzdata.noarch 0:2018i-1.el7

Complete!
Removing intermediate container 66eb8c88d680
 ---> 7827c1f58d69
Step 5/12 : RUN yum install httpd -y
 ---> Running in b3b027cccc5b
Loaded plugins: fastestmirror, ovl
Loading mirror speeds from cached hostfile
 * base: centos-hn.viettelidc.com.vn
 * extras: centos-hn.viettelidc.com.vn
 * updates: centos-hn.viettelidc.com.vn
Resolving Dependencies
--> Running transaction check
---> Package httpd.x86_64 0:2.4.6-88.el7.centos will be installed
--> Processing Dependency: httpd-tools = 2.4.6-88.el7.centos for package: httpd-2.4.6-88.el7.centos.x86_64
--> Processing Dependency: system-logos >= 7.92.1-1 for package: httpd-2.4.6-88.el7.centos.x86_64
--> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-88.el7.centos.x86_64
--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.4.6-88.el7.centos.x86_64
--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.4.6-88.el7.centos.x86_64
--> Running transaction check
---> Package apr.x86_64 0:1.4.8-3.el7_4.1 will be installed
---> Package apr-util.x86_64 0:1.5.2-6.el7 will be installed
---> Package centos-logos.noarch 0:70.0.6-3.el7.centos will be installed
---> Package httpd-tools.x86_64 0:2.4.6-88.el7.centos will be installed
---> Package mailcap.noarch 0:2.1.41-2.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
 Package             Arch          Version                    Repository   Size
================================================================================
Installing:
 httpd               x86_64        2.4.6-88.el7.centos        base        2.7 M
Installing for dependencies:
 apr                 x86_64        1.4.8-3.el7_4.1            base        103 k
 apr-util            x86_64        1.5.2-6.el7                base         92 k
 centos-logos        noarch        70.0.6-3.el7.centos        base         21 M
 httpd-tools         x86_64        2.4.6-88.el7.centos        base         90 k
 mailcap             noarch        2.1.41-2.el7               base         31 k

Transaction Summary
================================================================================
Install  1 Package (+5 Dependent packages)

Total download size: 24 M
Installed size: 31 M
Downloading packages:
--------------------------------------------------------------------------------
Total                                              4.9 MB/s |  24 MB  00:04
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : apr-1.4.8-3.el7_4.1.x86_64                                   1/6
  Installing : apr-util-1.5.2-6.el7.x86_64                                  2/6
  Installing : httpd-tools-2.4.6-88.el7.centos.x86_64                       3/6
  Installing : centos-logos-70.0.6-3.el7.centos.noarch                      4/6
  Installing : mailcap-2.1.41-2.el7.noarch                                  5/6
  Installing : httpd-2.4.6-88.el7.centos.x86_64                             6/6
  Verifying  : mailcap-2.1.41-2.el7.noarch                                  1/6
  Verifying  : apr-util-1.5.2-6.el7.x86_64                                  2/6
  Verifying  : httpd-tools-2.4.6-88.el7.centos.x86_64                       3/6
  Verifying  : httpd-2.4.6-88.el7.centos.x86_64                             4/6
  Verifying  : apr-1.4.8-3.el7_4.1.x86_64                                   5/6
  Verifying  : centos-logos-70.0.6-3.el7.centos.noarch                      6/6

Installed:
  httpd.x86_64 0:2.4.6-88.el7.centos

Dependency Installed:
  apr.x86_64 0:1.4.8-3.el7_4.1
  apr-util.x86_64 0:1.5.2-6.el7
  centos-logos.noarch 0:70.0.6-3.el7.centos
  httpd-tools.x86_64 0:2.4.6-88.el7.centos
  mailcap.noarch 0:2.1.41-2.el7

Complete!
Removing intermediate container b3b027cccc5b
 ---> ceaa2c4dc611
Step 6/12 : ENV source /var/www/html/
 ---> Running in 0dae76377156
Removing intermediate container 0dae76377156
 ---> 3d6abf9b4e60
Step 7/12 : VOLUME ["/var/log/httpd"]
 ---> Running in a5851687922f
Removing intermediate container a5851687922f
 ---> 5bedc77aef79
Step 8/12 : COPY index.html ${source}
 ---> 233244890ca7
Step 9/12 : COPY start.sh /start.sh
 ---> dde006532a47
Step 10/12 : RUN chmod +x /start.sh
 ---> Running in e639aca6cafe
Removing intermediate container e639aca6cafe
 ---> eeb387dba352
Step 11/12 : CMD ["/start.sh"]
 ---> Running in 2ae88e34619b
Removing intermediate container 2ae88e34619b
 ---> 1e9cab6ef65f
Step 12/12 : EXPOSE 80
 ---> Running in e697bcee7199
Removing intermediate container e697bcee7199
 ---> 97ba637ff1df
Successfully built 97ba637ff1df
Successfully tagged huytm/centos7-httpd:latest

f. Kiểm tra lại image vừa build

docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
huytm/centos7-httpd   latest              97ba637ff1df        4 minutes ago       457MB
centos                centos7             1e1148e4cc2c        2 months ago        202MB

g. Chạy container với image vừa build

docker run -itd -p 9000:80 --name huytm huytm/centos7-httpd

h. Truy cập vào apache của container

Truy cập vào apache của container theo địa chỉ

http://<Docker_host_ip>:9000


Tổng kết

Như vậy, trong bài viết này mình đã giới thiệu cách build một image từ Dockerfile cũng như giải thích các command trong cấu trúc file của Dockerfile.

Ở bài viết tiếp theo mình sẽ viết về các command cở của Docker, để thao tác với container.

“if you have knowledge let others light their candles in it”


Tài liệu tham khảo

https://docs.docker.com/engine/reference/builder/


Thực hiện bởi cloud365.vn

Written by Trần Mạnh Huy
×

Subscribe

The latest tutorials sent straight to your inbox.