Multi phase construction of front-end docker image

1. Front end image construction record

1. dockerfile

# Phase I
FROM node:latest AS build
ARG COSTAR_ENV
ENV COSTAR_ENV=${COSTAR_ENV}
COPY . .

RUN npm config set registry https://registry.npm.taobao.org/ && \
    npm install && \
    npm run dev_build && \
    mv dist web_portal && \
    cp -r web_portal /www/

# Phase II
FROM nginx:latest
ARG COSTAR_ENV
ENV COSTAR_ENV=${COSTAR_ENV}
# Delete the default nginx configuration default conf nginx. conf
RUN rm /etc/nginx/conf.d/default.conf && rm /etc/nginx/nginx.conf
COPY ./config/nginx/nginx.conf /etc/nginx/
COPY ./config/nginx/web_portal.conf /etc/nginx/sites-enabled/
COPY --from=build /www /www/web_portal/

Including nginx Conf to add a sentence, because the default file does not exist, delete it first (rm /etc/nginx/nginx.conf), and then insert the COPY written by yourself (COPY. / config / nginx / nginx.conf / etc / nginx /):

2.web_portal.conf

/etc/nginx/sites-enabled/web_portal.conf

##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or Wordpress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##

# Default server configuration
#
server {
    # Note: write your own front-end port here!!!!!!!!!!!!!
	listen 6060;
	server_name localhost;

	# SSL configuration
	#
	# listen 443 ssl default_server;
	# listen [::]:443 ssl default_server;
	#
	# Note: You should disable gzip for SSL traffic.
	# See: https://bugs.debian.org/773332
	#
	# Read up on ssl_ciphers to ensure a secure configuration.
	# See: https://bugs.debian.org/765782
	#
	# Self signed certs generated by the ssl-cert package
	# Don't use them in a production server!
	#
	# include snippets/snakeoil.conf;

	root /www/web_portal;
        location = /50x.html {
             root   html;
         }

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;
	#location ~ \.php$ {
	#	include snippets/fastcgi-php.conf;
	#
	#	# With php-fpm (or other unix sockets):
	#	fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
	#	# With php-cgi (or other tcp sockets):
	#	fastcgi_pass 127.0.0.1:9000;
	#}

	# deny access to .htaccess files, if Apache's document root
	# concurs with nginx's one
	#
	#location ~ /\.ht {
	#	deny all;
	#}
	location / {
          try_files $uri $uri/ /index.html;
        }
}


# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
#	listen 80;
#	listen [::]:80;
#
#	server_name example.com;
#
#	root /var/www/example.com;
#	index index.html;
#
#	location / {
#		try_files $uri $uri/ =404;
#	}
#}

3.nginx.conf

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
	worker_connections 768;
	# multi_accept on;
}

http {

	##
	# Basic Settings
	##

	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 65;
	types_hash_max_size 2048;
	# server_tokens off;

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	##
	# SSL Settings
	##

	ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
	ssl_prefer_server_ciphers on;

	##
	# Logging Settings
	##

	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;

	##
	# Gzip Settings
	##

	gzip on;

	# gzip_vary on;
	# gzip_proxied any;
	# gzip_comp_level 6;
	# gzip_buffers 16 8k;
	# gzip_http_version 1.1;
	# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

	##
	# Virtual Host Configs
	##
	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}


#mail {
#	# See sample authentication script at:
#	# http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
#	# auth_http localhost/auth.php;
#	# pop3_capabilities "TOP" "USER";
#	# imap_capabilities "IMAP4rev1" "UIDPLUS";
#
#	server {
#		listen     localhost:110;
#		protocol   pop3;
#		proxy      on;
#	}
#
#	server {
#		listen     localhost:143;
#		protocol   imap;
#		proxy      on;
#	}
#}

2. Dockerfile instruction COPY folder

Reprinted in https://www.iszy.cc/posts/13/

In particular, pay attention to the state of the copied folder when copying. The contents of the copied file may be copied in the past, but the folder itself is not copied.

Background description

Today, when copying the folder to the image through dockerfile, I found that the contents under the folder were copied in.

The dockerfile is as follows:

FROM node:alpine
WORKDIR /usr/src/app
COPY dist node_modules package.json ./
EXPOSE 3000
CMD ["yarn", "start:prod"]

I want to put dist and node_ Both modules folders are copied to the image, and you don't want to COPY them separately with multiple copies, so there will be one more layer. Dist and node were found_ Modules the two folders themselves are not copied into the image, but the contents under the folder are copied into the image respectively.

After testing, it is found that:

  • The ADD and COPY commands behave the same when copying files
  • If the source of the COPY/ADD command is a folder, the contents of the folder are copied instead of itself
  • Use * to match all files. If a folder is encountered, the above logic will be maintained, that is, only the content will be copied

This logic is very strange, which is inconsistent with our general expectations.

I found that someone had asked similar questions six years ago. It seems that there is nothing to change.

Implementation method

Here are a few ways for you to refer to.

Single folder replication, specifying the target directory

One way is to COPY one folder at a time, and then specify the specific directory in the image when copying. For example, change the dockerfile above to this:

FROM node:alpine
WORKDIR /usr/src/app
COPY dist ./dist
COPY node_modules ./node_modules
COPY package.json ./
EXPOSE 3000
CMD ["yarn", "start:prod"]

Put it in another folder and copy it uniformly

The above way of writing is very troublesome, and the number of layer s will be increased. I think of a disguised method here, which is not very elegant.

That is, put all the folders to be copied into a unified folder, and then copy this folder in dockerfile, and the directory structure under the folder can be maintained.

mkdir dockerPackages && mv dist node_modules dockerPackages
FROM node:alpine
WORKDIR /usr/src/app
COPY dockerPackages package.json ./
EXPOSE 3000
CMD ["yarn", "start:prod"]

Use Docker ignore file

In fact, the way we write above is like completing one thing, that is to copy only part of the content into the image, and then ignore other content. In this way, we can make use of it Docker ignore file to achieve more elegant implementation. Ignore all files first, and then exclude the files we need to copy.

.dockerignore:

*
!dist
!node_modules
!package.json
FROM node:alpine
WORKDIR /usr/src/app
COPY . ./
EXPOSE 3000
CMD ["yarn", "start:prod"]

Keywords: Front-end Linux Docker Nginx

Added by ciaran on Mon, 07 Feb 2022 02:37:06 +0200