Слишком много несоответствия тегов в инструменте android-sdk, не удается создать изображение docker

#android #docker #shell

#Android #docker #оболочка

Вопрос:

Я запускаю эту команду в docker для установки некоторых компонентов android-sdk:

 RUN mkdir ${ANDROID_HOME} amp;amp; wget --output-document=android-sdk.zip https://dl.google.com/android/repository/commandlinetools-linux-6609375_latest.zip 
    amp;amp; unzip android-sdk.zip -d ${ANDROID_HOME} 
    amp;amp; echo y | ${SDKMANAGER} --sdk_root=${ANDROID_HOME} --list 
    amp;amp; echo y | ${SDKMANAGER} --sdk_root=${ANDROID_HOME} "build-tools;25.0.1" 
    amp;amp; echo y | ${SDKMANAGER} --sdk_root=${ANDROID_HOME} "build-tools;28.0.3" 
    amp;amp; echo y | ${SDKMANAGER} --sdk_root=${ANDROID_HOME} "build-tools;29.0.2" 
    amp;amp; echo y | ${SDKMANAGER} --sdk_root=${ANDROID_HOME} "platform-tools" 
    amp;amp; echo y | ${SDKMANAGER} --sdk_root=${ANDROID_HOME} "platforms;android-25" 
    amp;amp; echo y | ${SDKMANAGER} --sdk_root=${ANDROID_HOME} "platforms;android-28" 
    amp;amp; echo y | ${SDKMANAGER} --sdk_root=${ANDROID_HOME} "platforms;android-30"  
    amp;amp; echo y | ${SDKMANAGER} --sdk_root=${ANDROID_HOME} "extras;android;m2repository" 
    amp;amp; echo y | ${SDKMANAGER} --sdk_root=${ANDROID_HOME} "extras;google;google_play_services" 
    amp;amp; ${SDKMANAGER} --sdk_root=${ANDROID_HOME} "ndk;${ANDROID_NDK_VERSION}" 
    amp;amp; ${SDKMANAGER} --sdk_root=${ANDROID_HOME} "cmake;3.10.2.4988404" 
    amp;amp; yes | ${SDKMANAGER} --sdk_root=${ANDROID_HOME} --update
  

поскольку это изображение docker, я должен запускать все в одной команде, иначе изображения будут иметь слишком много дополнительных слоев и занимать слишком много места.

Проблема в том, что из-за ненадежного интернета mu очень вероятно, что я получаю несоответствие тегов для одного из устанавливаемых компонентов, что заставляет меня снова запускать процесс. Мне приходится создавать свой образ docker более 30 раз, чтобы заставить его успешно выполнять все команды.

Есть ли способ повторить попытку при несоответствии тегов в android-sdk?

Я также подумал о попытке запустить каждую строку по отдельности, но все же внутри одной большой команды.

Может быть

 while true; do
    subcommand1
    if [ $? -eq 0 ]; then
        break
    fi
    sleep 1
done

while true; do
    subcommand2
    if [ $? -eq 0 ]; then
        break
    fi
    sleep 1
done
  

Это было бы легко сделать с файлом .sh, создав функцию, которая выполняет while цикл, но что, если я хочу сделать все в Dockerfile?

У кого-нибудь есть идея получше?

Ответ №1:

Отказ от ответственности: я понятия не имею, что делает ваша команда (помимо загрузки android-sdk), поэтому вам может потребоваться немного изменить мой код, чтобы заставить его работать.Кроме того, ваше изображение может не включать timeout

Во-первых, я бы начал с перемещения вашего скрипта в отдельный файл в том же каталоге, что и ваш Dockerfile , а затем выполнил его следующим образом:

 COPY ./build.sh .
RUN chmod  x ./build.sh amp;amp; ./build.sh
  

Теперь в скрипте вы можете проверить вывод каждой строки, прежде чем продолжить:

 #!/bin/bash

url="https://dl.google.com/android/repository/commandlinetools-linux-6609375_latest.zip"

mkdir ${ANDROID_HOME}
until (
  wget --output-document=android-sdk.zip "$url" amp;amp; 
  unzip android-sdk.zip -d ${ANDROID_HOME} 
); do
  sleep 1
done

args=(
  "--list"
  "build-tools;25.0.1"
  "build-tools;28.0.3"
  "build-tools;29.0.2"
  "platform-tools"
  "platforms;android-25"
  "platforms;android-28"
  "platforms;android-30"
  "extras;android;m2repository"
  "extras;google;google_play_services"
)

# you may need to modify this slightly!
for arg in "${args[@]}";
do
  until ( echo y | ${SDKMANAGER} --sdk_root=${ANDROID_HOME} "$arg" ); do
    sleep 5
  done
done
  

Было бы неплохо установить тайм-аут, чтобы ваша сборка не застряла в бесконечном цикле. Вместо добавления 2 отдельных проверок в скрипт, я бы просто добавил его в Dockerfile :

 # might need adjusting
ARG MAX_TIMEOUT=60

COPY ./build.sh .
RUN chmod  x ./build.sh amp;amp; timeout -k $MAX_TIMEOUT ./build.sh
  

Я бы рекомендовал использовать это как Base Image для вашего основного проекта, а не включать его в один и тот же Dockerfile . Таким образом, если вам нужно переделать свой проект Dockerfile и перестроить его, вам не придется каждый раз перестраивать android-sdk.