Skip to content

Commit

Permalink
Split multistage dockerfile for building images
Browse files Browse the repository at this point in the history
This commit add 3 functions in tern\analyze\docker\dockerfile.py。

1. check_multistage_dockerfile() to check if the given dockerfile is a
multistage dockerfile, return True or Flase and the index of FROM line.

2. get_multistage_image_dockerfiles() to split multistage dockerfile
into seperate dockerfiles for build.

3. write_dockerfile_by_structure() to write a dockerfile by the dfobj
structure.

Fixes tern-tools#767.

Signed-off-by: WangJL <hazard15020@gmail.com>
  • Loading branch information
ForgetMe17 committed Aug 18, 2020
1 parent 044dc47 commit 5b18369
Showing 1 changed file with 49 additions and 0 deletions.
49 changes: 49 additions & 0 deletions tern/analyze/docker/dockerfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from dockerfile_parse import DockerfileParser
import re
import logging
import os

from tern.utils import general
from tern.utils import constants
Expand Down Expand Up @@ -333,3 +334,51 @@ def write_locked_dockerfile(dfile, destination=None):
file_name = constants.locked_dockerfile
with open(file_name, 'w') as f:
f.write(dfile)


def check_multistage_dockerfile(dfobj):
"""Given a dockerfile object, return the index(es) of FROM line(s)
in the dfobj structure."""
from_lines = []
for idx, st in enumerate(dfobj.structure):
if st['instruction'] == 'FROM':
from_lines.append(idx)
return from_lines


def get_multistage_image_dockerfiles(dfobj_multi):
"""Given a multistage dockerfile object, return a list of structures
for building image."""
file_path_list = []
structure = []
file_idx = 0
from_lines = check_multistage_dockerfile(dfobj_multi)
# Pop the first FROM
from_lines.pop(0)
# Get the temp folder path
temp_folder_path = os.path.dirname(dfobj_multi.filepath) + '/dftemp'
if not os.path.isdir(temp_folder_path):
os.mkdir(temp_folder_path)
for idx in range(len(dfobj_multi.structure)):
if idx in from_lines:
if structure:
df_folder_path = temp_folder_path + '/%d' % (file_idx)
# we make a new dir for the dockerfile of each stage.
if not os.path.isdir(df_folder_path):
os.mkdir(df_folder_path)
file_path = df_folder_path + '/Dockerfile'
file_idx += 1
write_dockerfile_by_structure(file_path, structure)
file_path_list.append(file_path)
structure.append(dfobj_multi.structure[idx])
if structure:
file_path_list.append(dfobj_multi.filepath)
return file_path_list


def write_dockerfile_by_structure(file_name, structure):
"""Given a dockerfile name and its structure, write the content into the
dockerfile."""
with open(file_name, 'w') as f:
for st in structure:
f.write(st['content'])

0 comments on commit 5b18369

Please sign in to comment.