The installation kubeadm-dind-cluster requires Internet, because both the script itself and kubeadm inside pulls Docker images from Docker Hub and Google Container Registry.
One way to avoid the Internet requirement is to host a local Docker registry preloaded with all images required and configure the cluster to pull from this local registry.
The setup below demonstration air gap installation of Kubernetes v1.13, tested with Ubuntu 18.04 and Docker CE 18.09.6.
# let's put all stuff here
mkdir kdc_offline
cd kdc_offline
# download assets
wget -O kubectl https://storage.googleapis.com/kubernetes-release/release/v1.13.8/bin/linux/amd64/kubectl
wget -O dind-cluster.sh 'https://github.com/kubernetes-sigs/kubeadm-dind-cluster/blob/814d9ca036b23adce9e6c683da532e8037820119/dind-cluster.sh?raw=true'
wget -O config.sh 'https://github.com/kubernetes-sigs/kubeadm-dind-cluster/blob/814d9ca036b23adce9e6c683da532e8037820119/config.sh?raw=true'
wget -O kubernetes-dashboard.yaml 'https://github.com/kubernetes/dashboard/blob/bfab10151f012d1acc5dfb1979f3172e2400aa3c/src/deploy/kubernetes-dashboard.yaml?raw=true'
# update to use local registry
sed -i 's|gcr.io/google_containers|registry:5000|' kubernetes-dashboard.yaml
cat <<EOF > Dockerfile
FROM mirantis/kubeadm-dind-cluster:814d9ca036b23adce9e6c683da532e8037820119-v1.13
RUN sed -i '/kind: ClusterConfiguration/a imageRepository: registry:5000' /etc/kubeadm.conf.1.13.tmpl
EOF
docker build -t mirantis/kubeadm-dind-cluster .
# download images
mkdir images
cd images
docker pull registry:2.7.1
docker tag registry:2.7.1 registry:latest
# these version are found from cluster created by dind-cluster.sh with Internet
docker pull k8s.gcr.io/etcd:3.2.24
docker pull k8s.gcr.io/coredns:1.2.6
docker pull k8s.gcr.io/pause:3.1
docker pull k8s.gcr.io/hyperkube:v1.13.5
# this version is found from kubernetes-dashboard.yaml dowloaded above
docker pull gcr.io/google_containers/kubernetes-dashboard-amd64:v1.6.0
# save images to files
docker save registry:2.7.1 registry:latest > registry.tar
docker save mirantis/kubeadm-dind-cluster:latest > kdc.tar
docker save k8s.gcr.io/etcd:3.2.24 > k8s.etcd.tar
docker save k8s.gcr.io/coredns:1.2.6 > k8s.coredns.tar
docker save k8s.gcr.io/pause:3.1 > k8s.pause.tar
docker save k8s.gcr.io/hyperkube:v1.13.5 > k8s.hyperkube.tar
docker save gcr.io/google_containers/kubernetes-dashboard-amd64:v1.6.0 > k8s.dashboard.tar
# load images to host docker
cd kdc_offline
find images/*.tar -exec docker load -i {} \;
# create cluster network, should fit the config of dind-cluster.sh
docker network create --subnet='10.192.0.0/24' --gateway='10.192.0.1' kubeadm-dind-net
# create volume for registry
docker volume create registry
# start registry
# attaching to the cluster network.
# dind-cluster.sh will set master IP to 10.192.0.2, node 1 IP to 10.192.0.3 and so on.
# Thus we need to assign IP to registry to avoid conflict.
docker run -d --net kubeadm-dind-net --name registry --hostname registry --ip 10.192.0.254 -v registry:/var/lib/registry -p 5000:5000 registry
# push images to registry
IMAGES="k8s.gcr.io/etcd:3.2.24
k8s.gcr.io/pause:3.1
k8s.gcr.io/coredns:1.2.6
gcr.io/google_containers/kubernetes-dashboard-amd64:v1.6.0
k8s.gcr.io/hyperkube:v1.13.5"
echo "$IMAGES" | xargs -i bash -c 'NAME=$(basename {}); IMG=127.0.0.1:5000/$NAME; docker tag {} $IMG; docker push $IMG;'
# install kubectl
sudo cp kubectl /usr/local/bin/
sudo chmod +x /usr/local/bin/kubectl
# start the cluster
# for persisted config, set variables in config.sh instead of export
export DIND_INSECURE_REGISTRIES="[\"0.0.0.0/0\"]"
export DIND_IMAGE=mirantis/kubeadm-dind-cluster
export DASHBOARD_URL=$PWD/kubernetes-dashboard.yaml
export DIND_SKIP_PULL=true
bash dind-cluster.sh up
For subsequent starts, only the 'start registry' and 'start the cluster' sections are needed.