আমি কীভাবে কোনও ডকার পাত্রে উঠতে এবং চালিত হওয়ার জন্য অপেক্ষা করতে পারি?


85

কোনও ধারকের ভিতরে কোনও পরিষেবা চালানোর সময়, কমান্ডটি মঙ্গডব বলি

docker run -d myimage

তাত্ক্ষণিকভাবে প্রস্থান করা হবে, এবং ধারক আইডি ফেরত হবে আমার সিআই স্ক্রিপ্টে, আমি মঙ্গো কনটেইনারটি চালানোর ঠিক পরে, মঙ্গোদ্ব সংযোগ পরীক্ষা করার জন্য একটি ক্লায়েন্ট চালাচ্ছি। সমস্যাটি হ'ল: ক্লায়েন্ট সংযোগ দিতে পারে না কারণ পরিষেবাটি এখনও শেষ হয়নি। sleep 10আমার স্ক্রিপ্টে একটি বড় যোগ করা ছাড়াও , আমি কোনও ধারক উঠার জন্য অপেক্ষা করার কোনও বিকল্প দেখতে পাচ্ছি না।

ডকারের একটি কমান্ড রয়েছে waitযা সেই ক্ষেত্রে কাজ করে না, কারণ ধারকটি নেই। এটি কি ডকারের সীমাবদ্ধতা?


আরও দেখুন : ডকার
কমপ্লেট

উত্তর:


51

ডকার 1.12 এর অনুরূপ ইস্যুতে মন্তব্য করা হয়েছে

HEALTHCHECKসমর্থন ডকার / ডকার # 23218 অনুযায়ী আপ স্ট্রিমকে একত্রিত করা হয়েছে - ক্রমটি পরবর্তী শুরু করার আগে কোনও ধারক কখন সুস্থ থাকে তা নির্ধারণ করার জন্য এটি বিবেচনা করা যেতে পারে

এটি ডকার 1.12rc3 (2016-07-14) থেকে পাওয়া যায়

docker-composeনির্দিষ্ট শর্তের জন্য অপেক্ষা করার জন্য কোনও কার্যকারিতা সমর্থন করার প্রক্রিয়াতে রয়েছে।

এটি ব্যবহার করে libcompose(সুতরাং আমাকে ডকার ইন্টারঅ্যাকশনটি পুনরায় তৈরি করতে হবে না) এবং এটির জন্য কনফিগার কমান্ডগুলির একটি গুচ্ছ যুক্ত করে। এটি এখানে দেখুন: https://github.com/dansteen/controlled-compose

আপনি এটি ডকঅফাইলে এটির মতো ব্যবহার করতে পারেন:

HEALTHCHECK --interval=5m --timeout=3s \
  CMD curl -f http://localhost/ || exit 1

অফিসিয়াল ডক্স: https://docs.docker.com/engine/references/builder/#/healthcheck


আমি আশা করছিলাম যে এটি সবচেয়ে বেশি ভোট হবে। তবে আমি আবিষ্কার করেছি যে এটি খুব সম্প্রতি উত্তর দেওয়া হয়েছিল।
শিপলু মোকাদ্দিম

55

এই সহজ সমাধানটি খুঁজে পেয়েছি, আরও ভাল কিছু খুঁজছেন তবে ভাগ্য নেই ...

until [ "`/usr/bin/docker inspect -f {{.State.Running}} CONTAINERNAME`"=="true" ]; do
    sleep 0.1;
done;

অথবা যদি আপনি ধারকটি স্বাস্থ্যকর হিসাবে রিপোর্ট না করা অবধি অপেক্ষা করতে চান (ধরে নিলেন আপনার একটি স্বাস্থ্য পরীক্ষা রয়েছে)

until [ "`/usr/bin/docker inspect -f {{.State.Health.Status}} CONTAINERNAME`"=="healthy" ]; do
    sleep 0.1;
done;

4
পরিবর্তে লুপ ব্যবহার করার সময় একটি লাইনারwhile [ "`docker inspect -f {{.State.Health.Status}} $container_id`" != "healthy" ]; do sleep 2; done
মওথ

কেবল একটি টীকা, ডকার ওএসএক্সে / ইউএসআর / লোকাল / বিন / ডকারে রয়েছে। স্ক্রিপ্টটি ক্রস-প্ল্যাটফর্ম করতে $ (কোন ডকার) যুক্ত করার উপযুক্ত হতে পারে?
con--

@ কন-- নিশ্চিত, এটি একটি উন্নতি হবে যদিও আমি "ক্রস প্ল্যাটফর্ম স্ক্রিপ্টস" এর ডকুমেন্টেশনকে প্রশ্নের ক্ষেত্রের বাহ্যিক উদ্বেগ হিসাবে বিবেচনা করি। কখনও কম নয়, আপনি যদি সম্পাদনা করতে চান তবে এর জন্য যান :)
সুপারহিরো

4
এটি আমার সাথে এইভাবে কাজ করেছে: #! / বিন / বাশ পর্যন্ত /usr/bin/docker inspect -f {{.State.Running}} local_mysql== সত্য $ ঘুমো না 0.1; সম্পন্ন; প্রতিধ্বনি "
মাইএসকিএল

@ এম.হফনি উত্তরের একই উদাহরণ যা উত্তরে প্রকাশিত হয়েছে।
সুপারহিরো

32

আপনি যদি বন্দরগুলি প্রকাশ করতে না চান, যেমনটি আপনি যদি ধারকটিকে লিঙ্ক করার পরিকল্পনা করেন এবং পরীক্ষার জন্য একাধিক উদাহরণ চালাচ্ছেন, তবে আমি খুঁজে পেলাম এটি একটি লাইনে এটি করার একটি ভাল উপায় ছিল :) এই উদাহরণটি হ'ল ইলাস্টিক অনুসন্ধান অনুসন্ধানের জন্য অপেক্ষা করার ভিত্তিতে:

docker inspect --format '{{ .NetworkSettings.IPAddress }}:9200' elasticsearch | xargs wget --retry-connrefused --tries=5 -q --wait=3 --spider

এর জন্য উইজেট পাওয়া দরকার যা উবুন্টুতে মান standard এটি 5 বার, আবার চেষ্টা করার মধ্যে 3 সেকেন্ডের মধ্যে আবার চেষ্টা করবে, এমনকি সংযোগটি অস্বীকার করা হলেও, এবং কিছু ডাউনলোড না করে not


আমি মনে করি আপনি এর --waitretry=3পরিবর্তে ব্যবহার করতে চান--wait=3
jpbochi

কৌতূহলী, উইজেট ম্যান পৃষ্ঠা --wait=seconds Wait the specified number of seconds between the retrievals. এবং --waitretry=seconds If you don't want Wget to wait between every retrieval, but only between retries of failed downloads, you can use this option. Wget will use linear backoff, waiting 1 second after the first failure on a given file, then waiting 2 seconds after the second failure on that file, up to the maximum number of seconds you specify.
লক্ষ্যবিহীন

25

আপনি যে কন্টেইনারযুক্ত পরিষেবাটি শুরু করেছেন অগত্যা কার্ল বা উইজেট অনুরোধগুলির (যা বেশ কয়েকটি পরিষেবার ক্ষেত্রে সম্ভবত সম্ভবত) ভালভাবে সাড়া না দেয় তবে আপনি তার ncপরিবর্তে ব্যবহার করতে পারেন ।

এখানে একটি হোস্ট স্ক্রিপ্টের স্নিপেট রয়েছে যা একটি পোস্টগ্রাস ধারক শুরু করে এবং এটি চালিয়ে যাওয়ার আগে এটি উপলব্ধ হওয়ার জন্য অপেক্ষা করে:

POSTGRES_CONTAINER=`docker run -d --name postgres postgres:9.3`
# Wait for the postgres port to be available
until nc -z $(sudo docker inspect --format='{{.NetworkSettings.IPAddress}}' $POSTGRES_CONTAINER) 5432
do
    echo "waiting for postgres container..."
    sleep 0.5
done

সম্পাদনা করুন - এই উদাহরণটির প্রয়োজন নেই যে আপনি যে পোর্টটি পরীক্ষা করছেন সেটি এক্সপোজ করুন, কারণ এটি ধারকটির জন্য ডকার-নির্ধারিত 'ব্যক্তিগত' আইপি ঠিকানাটি অ্যাক্সেস করে। তবে এটি কেবল তখনই কাজ করে যদি ডকার হোস্ট ডিমন লুপব্যাক (127.xxx) এ শুনছে। যদি (উদাহরণস্বরূপ) আপনি ম্যাকের উপরে চলেছেন এবং বুট 2 ডকার ভিএম চালাচ্ছেন তবে আপনি এই পদ্ধতিটি ব্যবহার করতে পারবেন না যেহেতু আপনি আপনার ম্যাক শেল থেকে পাত্রে 'ব্যক্তিগত' আইপি ঠিকানাগুলিতে রুট করতে পারবেন না।


আমি বিশ্বাস করি যে --formatএই উত্তরটির পরে বিকল্পটি পরিবর্তিত হয়েছে; এখন কী কাজ করে তা হ'ল docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' [NAME|ID...]( docs.docker.com/engine/references/commandline/inspect এ উদাহরণ দেখুন )।
কুর্ট পিক

16

ধরে নিই যে আপনি আপনার মঙ্গোডিবি সার্ভারের হোস্ট + পোর্টটি জানেন (যদি আপনি একটি ব্যবহার করেছিলেন -link, অথবা আপনি সেগুলি ইনজেকশনের কারণে করেছেন -e) তবে আপনি কেবল curlমংগোডিবি সার্ভারটি চালু রয়েছে এবং সংযোগগুলি গ্রহণ করছেন কিনা তা পরীক্ষা করে দেখতে পারেন।

নিম্নলিখিত স্নিপেটটি যতক্ষণ না সফল হয় প্রতি সেকেন্ডে সংযুক্ত হওয়ার চেষ্টা করবে:

#!/bin/sh
while ! curl http://$DB_PORT_27017_TCP_ADDR:$DB_PORT_27017_TCP_PORT/
do
  echo "$(date) - still trying"
  sleep 1
done
echo "$(date) - connected successfully"

4
তবে আপনাকে হোস্টের উপর বন্দরটি আবদ্ধ করতে হবে :(
গ্রাভিস

আমি একই সমস্যা পেয়েছি। পিডফাইল ব্যবহার করে মনিট সেট আপ করার চেষ্টা করা এবং ম্যানুয়ালি ভার্সে ইনজেকশন না দিয়ে ডকার শুরু / থামাতে কোনও দানাদার ইভেন্টটি ট্রিগার করতে সক্ষম না হওয়া একটি ব্যথা, এর অর্থ আমি কেবল জেনেরিক মোড়কে সহজেই লিখতে পারি না।
অ্যালেক্স লিনহ্যাম

তোমার সাথে যেতে পারি IP=$(docker inspect -f '{{ .NetworkSettings.IPAddress }}' mysql)আপনার MySQL ধারক (যেখানে "MySQL" নাম বা ধারক আইডি হয়) IP ঠিকানা পেতে এবং url সহ প্রতিস্থাপন: http://$IP:3306। আমার জন্য কাজ কর!
ড্যানিয়েল

12

আমি এরকম কিছু দিয়ে শেষ করেছি:

#!/bin/bash

attempt=0
while [ $attempt -le 59 ]; do
    attempt=$(( $attempt + 1 ))
    echo "Waiting for server to be up (attempt: $attempt)..."
    result=$(docker logs mongo)
    if grep -q 'waiting for connections on port 27017' <<< $result ; then
      echo "Mongodb is up!"
      break
    fi
    sleep 2
done

10

আমার নিজের সমাধানটি সেখানে ফেলে দিচ্ছি:

আমি ডকার নেটওয়ার্কগুলি ব্যবহার করছি যাতে মার্কের নেটক্যাট ট্রিকটি আমার পক্ষে কাজ করে না (হোস্ট নেটওয়ার্ক থেকে অ্যাক্সেস পায় না) এবং এরিকের ধারণা পোস্টগ্রিস কনটেইনারটির পক্ষে কাজ করে না (পোস্টার এখনও না হলেও কনটেইনারটি চলমান হিসাবে চিহ্নিত হয়েছে) সংযোগ করার জন্য উপলব্ধ)। সুতরাং আমি কেবল একটি লুপে একটি সাময়িক ধারক মাধ্যমে পোস্টগ্রিজের সাথে সংযোগ করার চেষ্টা করছি:

#!/bin/bash

docker network create my-network
docker run -d \
    --name postgres \
    --net my-network \
    -e POSTGRES_USER=myuser \
    postgres

# wait for the database to come up
until docker run --rm --net my-network postgres psql -h postgres -U myuser; do
    echo "Waiting for postgres container..."
    sleep 0.5
done

# do stuff with the database...

আজ আমরা এটিই করছি। পোস্টগ্রিজ চিত্রটি সম্পর্কে সাবধানতা অবলম্বন করুন, সার্ভারটি একবার শুরু হওয়ার আগে, পুনরায় চালু করার আগে ...
গ্রাভিস

এটি কয়েকটি ছোটখাটো পরিবর্তন সহ ভাল কাজ করে। 1. postgresহোস্ট সমাধান হয় না, তাই আমি docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' postgresপরিবর্তে ব্যবহার । ২. psqlএকটি পাসওয়ার্ড প্রয়োজন, pg_isreadyএটি আরও ভাল ফিট। ৩. এর সাথে pg_isreadyকোনও দরকার নেই -U myuser
আলেক মেভ

2

test/test_runner

#!/usr/bin/env ruby

$stdout.sync = true

def wait_ready(port)
  until (`netstat -ant | grep #{port}`; $?.success?) do
    sleep 1
    print '.'
  end
end

print 'Running supervisord'
system '/usr/bin/supervisord'

wait_ready(3000)

puts "It's ready :)"

$ docker run -v /tmp/mnt:/mnt myimage ruby mnt/test/test_runner

আমি বন্দরটি শুনছে কি শুনছে না সেভাবেই এটি পরীক্ষা করছি। এক্ষেত্রে আমার ভেতরের পাত্রে পরীক্ষা চলছে, তবে মঙ্গোদব প্রস্তুত কিনা তা বাইরে থেকে এটিও সম্ভব।

$ docker run -p 37017:27017 -d myimage

এবং পোর্টটি 37017 হোস্ট কনটেইনার থেকে শুনছে কি না তা পরীক্ষা করে দেখুন।


2

আমাকে এই নিখুঁতভাবে মোকাবেলা করতে হবে এবং একটি ধারণা নিয়ে এসেছি। এই কাজের জন্য গবেষণা করার সময় আমি এখানে পৌঁছেছি, তাই আমি ভেবেছিলাম যে আমি এই পোস্টটির ভবিষ্যতের দর্শকদের সাথে আমার সমাধানটি ভাগ করব।

ডকার-রচনা-ভিত্তিক সমাধান

আপনি যদি ডকার-রচনা ব্যবহার করছেন তবে আপনি আমার ডকার সিঙ্ক্রোনাইজেশন পিওসি পরীক্ষা করে দেখতে পারেন । আমি অন্যান্য প্রশ্নের মধ্যে কিছু ধারণাগুলি একত্রিত করেছি (এর জন্য ধন্যবাদ - উত্সাহিত)।

মূল ধারণাটি হ'ল যৌগের প্রতিটি ধারক একটি ডায়াগনস্টিক পরিষেবাটি প্রকাশ করে। এই পরিষেবাটি কল করে কনটেইনারটিতে প্রয়োজনীয় বন্দরগুলির সেটটি খোলা রয়েছে এবং কনটেইনারটির সামগ্রিক স্থিতি (পিওসি অনুসারে ওয়ার্মআপ / রুনিং) প্রদান করে কিনা তা পরীক্ষা করে। যদি নির্ভরশীল পরিষেবাগুলি চালু থাকে এবং চলমান থাকে তবে প্রতিটি পাত্রে স্টার্টআপ পরীক্ষা করার জন্যও একটি উপযোগ রয়েছে। তবেই ধারকটি শুরু হয়।

উদাহরণস্বরূপ ডকার-রচনা পরিবেশে দুটি পরিষেবা সার্ভার 1 এবং সার্ভার 2 রয়েছে এবং ক্লায়েন্ট পরিষেবা যা উভয় সার্ভার শুরু হওয়ার জন্য অপেক্ষা করে তারপরে উভয়কে অনুরোধ প্রেরণ করে প্রস্থান করে।

পিওসি থেকে অংশ

অপেক্ষা_ফোর্স_সার্ভার.শ

#!/bin/bash

server_host=$1
sleep_seconds=5

while true; do
    echo -n "Checking $server_host status... "

    output=$(echo "" | nc $server_host 7070)

    if [ "$output" == "RUNNING" ]
    then
        echo "$server_host is running and ready to process requests."
        break
    fi

    echo "$server_host is warming up. Trying again in $sleep_seconds seconds..."
    sleep $sleep_seconds
done

একাধিক পাত্রে অপেক্ষা করা:

trap 'kill $(jobs -p)' EXIT

for server in $DEPENDS_ON
do
    /assets/wait_for_server.sh $server &
    wait $!
done

ডায়াগনস্টিক srervice বেসিক বাস্তবায়ন ( চেকপোর্টস.শ ):

#!/bin/bash

for port in $SERVER_PORT; do
    nc -z localhost $port;

    rc=$?

    if [[ $rc != 0 ]]; then
        echo "WARMUP";
        exit;
    fi
done

echo "RUNNING";

একটি বন্দরে ডায়াগনস্টিক পরিষেবা ওয়্যারিং আপ:

nc -v -lk -p 7070 -e /assets/checkports.sh

আকর্ষণীয় পদ্ধতির। +1
ভোনসি

1

আপনি অপেক্ষার জন্য এটি ব্যবহার করতে পারেন , " একটি খাঁটি বাশ স্ক্রিপ্ট যা কোনও হোস্ট এবং টিসিপি পোর্টের উপলভ্যতার জন্য অপেক্ষা করবে inter এটি নির্ভরশীল পরিষেবাগুলির স্পিন-আপকে সংযুক্ত করার জন্য দরকারী যেমন লিংকড ডকার পাত্রে। এটি যেহেতু একটি খাঁটি বাশ স্ক্রিপ্ট, এটির কোনও বাহ্যিক নির্ভরতা নেই "।

তবে পরিষেবার মধ্যে এই ধরনের আন্তঃনির্ভরতা এড়াতে আপনার পরিষেবাগুলি ডিজাইনের চেষ্টা করা উচিত। আপনার পরিষেবাটি কি ডাটাবেসের সাথে পুনরায় সংযোগ স্থাপনের চেষ্টা করতে পারে? আপনি যদি আপনার ধারকটিকে ডেটাবেসের সাথে সংযুক্ত না করতে পারেন এবং কোনও ধারক অর্কেস্ট্রেটারকে (উদাহরণস্বরূপ ডকার সোর্ম) আপনার জন্য এটি করতে দেয় তবে আপনি কি তাকে মরে যেতে দিতে পারেন?


1

কোনও পোস্টগ্রেএসকিউএল বা মাইএসকিউএল (বর্তমানে) ডকার কন্টেইনারটি চালু এবং চলমান রয়েছে কিনা তা যাচাই করতে (বিশেষত ফ্লাইওয়ের মতো মাইগ্রেশন সরঞ্জামগুলির জন্য), আপনি বাইনারিটির জন্য অপেক্ষা করতে পারেন : https://github.com/ArcanjoQueiroz/wait- জন্য


0

ডকার-রচনা সমাধান

ডকার-রচনার পরে আমি ডকারের ধারকটির নাম জানি না, তাই আমি ব্যবহার করি

docker inspect -f {{.State.Running}} $(docker-compose ps -q <CONTAINER_NAME>)

এবং trueএখানে https://stackoverflow.com/a/33520390/7438079 এর মতো চেক করা হচ্ছে


0

মঙ্গোডিবি ডকার উদাহরণের জন্য আমরা এটি করেছি এবং একটি কবজির মতো কাজ করি:

#!/usr/bin/env bash

until docker exec -i ${MONGO_IMAGE_NAME} mongo -u ${MONGO_INITDB_ROOT_USERNAME} -p ${MONGO_INITDB_ROOT_PASSWORD}<<EOF
exit
EOF
do
    echo "Waiting for Mongo to start..."
    sleep 0.5
done
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.