Serverless Asterisk with Docker and AWS Fargate
Tags: docker, aws, linux, serverless
Published: 2020-05-13 09:20:02

Asterisk is a powerful freebase PBX providing VoIP and Telephony solutions, catering to the needs of both Enterprise and Stand-Alone levels. In the article below, we would demonstrate the creation of a highly-scalable Asterisk cloud server through Fargate task, which would require minimal maintenance and administration. 

#Prerequisite#

1.Docker installed on your personal machine.
2.An active AWS account for deploying images.
Note : You can use either of AWS EC2 or Cloud9 IDE for setting up Docker.

#Creating Asterisk on Docker#

####1.Creating the base image 

```
<pre><code class="language-bash">#base image for container
FROM debian:buster-slim
</code></pre>
```

We have chosen *Debian Buster Slim* for the base image as shown above. It is recommended that you keep the container light and use smallest size for the base image. You can also choose Alpine, Jessie or Stretch versions as per your convenience.

####2.Setting up Asterisk

```
#base image for container
$ docker build -t asterisk:latest 
Sending build context to Docker daemon  2.048kBStep 1/1 : FROM debian:buster-slim: Pulling from library/debian8ec398bc0356: Pull completeDigest: sha256:e4c1417236abc57971755ca2bfccd546cbca45b33daf66001a5addae4bf78517Status: Downloaded newer image for debian:buster-slim---> e1af56d072b8Successfully built e1af56d072b8Successfully tagged asterisk:latest
```

Use `docker build -t asterisk` to setup Asterisk on the Docker image.

```
$docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
<none>              <none>              a8b00d3e8229        37 minutes ago      592MB
asterisk            latest              e1af56d072b8        2 weeks ago         69.2MB
debian              buster-slim         e1af56d072b8        2 weeks ago         69.2MB
debian              latest              b5d2d9b1597b        2 weeks ago         114MB
```

As shown above, Asterisk is installed with image id **e1af56d072b8** showing the image size of **69.2 MB** which is tiny compared to the overall ISO size.

####3.Labeling the Asterisk image

```
#base image for container
FROM debian:buster-slim

LABEL maintainer="Bora Ozkan <boraozkan@gmail.com>"
```

Once the labeling is done, you can run `docker inspect` to do a quick inspection of the Docker image as shown below

```
$docker inspect asterisk:latest 
[
    {
        "Id": "sha256:d216cbd1c686b8afbcaab3406adf02a8ac481797510ea5a189ac1314ae654ead",
        "RepoTags": [
            "asterisk:latest"
        ],
        "RepoDigests": [],
        "Parent": "sha256:e1af56d072b8d93fce4b566f4bf76311108dbbbe952b12a85418bd32c2fcdda7",
        "Comment": "",
        "Created": "2020-01-14T09:06:47.708064046Z",
        "Container": "d552618057cb929857b2c9dbd1efa2f2be9d7e422c7ab85ff858fa2064398cb1",
        "ContainerConfig": {
            "Hostname": "d552618057cb",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "LABEL maintainer=Bora OZKAN <boraozkan@gmail.com>"
            ],
            "ArgsEscaped": true,
            "Image": "sha256:e1af56d072b8d93fce4b566f4bf76311108dbbbe952b12a85418bd32c2fcdda7",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "maintainer": "Bora OZKAN <boraozkan@gmail.com>"
            }
        },
        "DockerVersion": "18.09.7",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "bash"
            ],
            "ArgsEscaped": true,
            "Image": "sha256:e1af56d072b8d93fce4b566f4bf76311108dbbbe952b12a85418bd32c2fcdda7",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "maintainer": "Bora OZKAN <boraozkan@gmail.com>"
            }
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 69208427,
        "VirtualSize": 69208427,
        "GraphDriver": {
            "Data": {
                "MergedDir": "/var/lib/docker/overlay2/495f15d329ebee16bec4985ea625d8d835be42adac19cf075a3b998535bbd58e/merged",
                "UpperDir": "/var/lib/docker/overlay2/495f15d329ebee16bec4985ea625d8d835be42adac19cf075a3b998535bbd58e/diff",
                "WorkDir": "/var/lib/docker/overlay2/495f15d329ebee16bec4985ea625d8d835be42adac19cf075a3b998535bbd58e/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:556c5fb0d91b726083a8ce42e2faaed99f11bc68d3f70e2c7bbce87e7e0b3e10"
            ]
        },
        "Metadata": {
            "LastTagTime": "2020-01-14T09:06:47.718230311Z"
        }
    }
]
```

####4.Setting up Environment Variables

```
#base image for container
FROM debian:buster-slim

LABEL maintainer='Bora Ozkan <boraozkan@gmail.com>'

ENV ASTERISK_VERSION 17-current
ENV OPUS_CODEC       asterisk-17.0/x86-64/codec_opus-17.0_current-x86_64
```

The `ENV` instruction sets the environment variable which is important while installing Asterisk. Above we have created two environment values; first is defining the version while the second is for using *Default Codec*. 

```
#base image for container
FROM debian:buster-slim

LABEL maintainer='Bora Ozkan <boraozkan@gmail.com>'

ENV ASTERISK_VERSION 17-current
ENV OPUS_CODEC       asterisk-17.0/x86-64/codec_opus-17.0_current-x86_64

COPY build-asterisk.sh /
RUN /build-asterisk.sh
```

The `COPY` instruction copies files to the image directory as specified while building image, while the `RUN` instruction will execute any commands in a new layer on top of the current image and commit results. 

Now we can create our `build-asterisk.sh`

####5.Declaring commands

We start with declaring all commands to be run in the bash shell. For reference, we are checking if the `ASTERISK_VERSION` is higher than 2. 

```
#!/bin/bash
PROGNAME=$(basename $0)

if test -z ${ASTERISK_VERSION}; then
  echo "${PROGNAME}: ASTERISK_VERSION required" >&2
  exit 1
fi

set -ex

useradd --system asterisk
```

The `set -ex` command is quite useful instructing the process to exit when the step fails in bash script, along with tracing errors within the bash script.
 
Using `useradd` command for creating new system account named 'Asterisk'.

```
#!/bin/bash
PROGNAME=$(basename $0)

if test -z ${ASTERISK_VERSION}; then
  echo "${PROGNAME}: ASTERISK_VERSION required" >&2
  exit 1
fi

set -ex

useradd --system asterisk

apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends --no-install-suggests \
    autoconf \
    binutils-dev \
    build-essential \
    ca-certificates \
    curl \
    file \
    libcurl4-openssl-dev \
    libedit-dev \
    libgsm1-dev \
    libogg-dev \
    libpopt-dev \
    libresample1-dev \
    libspandsp-dev \
    libspeex-dev \
    libspeexdsp-dev \
    libsqlite3-dev \
    libsrtp2-dev \
    libssl-dev \
    libvorbis-dev \
    libxml2-dev \
    libxslt1-dev \
    procps \
    portaudio19-dev \
    unixodbc \
    unixodbc-bin \
    unixodbc-dev \
    odbcinst \
    uuid \
    uuid-dev \
    xmlstarlet
```

Above we are installing necessary libraries, as the base image being slim didn't had additional packages and modules. 

It is very important in Docker that each step works smoothly without error. To ensure this we can `DEBIAN_FRONTEND=noninteractive` and parameters. This will essentially install all modules, packages and libraries in *Quite Mode* and not attempt to CLI. This will also automate our installation, reducing manual time and effort considerably.

```
#!/bin/bash
PROGNAME=$(basename $0)

if test -z ${ASTERISK_VERSION}; then
  echo "${PROGNAME}: ASTERISK_VERSION required" >&2
  exit 1
fi

set -ex

useradd --system asterisk

apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends --no-install-suggests \
    autoconf \
    binutils-dev \
    build-essential \
    ca-certificates \
    curl \
    file \
    libcurl4-openssl-dev \
    libedit-dev \
    libgsm1-dev \
    libogg-dev \
    libpopt-dev \
    libresample1-dev \
    libspandsp-dev \
    libspeex-dev \
    libspeexdsp-dev \
    libsqlite3-dev \
    libsrtp2-dev \
    libssl-dev \
    libvorbis-dev \
    libxml2-dev \
    libxslt1-dev \
    procps \
    portaudio19-dev \
    unixodbc \
    unixodbc-bin \
    unixodbc-dev \
    odbcinst \
    uuid \
    uuid-dev \
    xmlstarlet
    
apt-get purge -y --auto-remove
rm -rf /var/lib/apt/lists/*

mkdir -p /usr/src/asterisk
cd /usr/src/asterisk

curl -vsL http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-${ASTERISK_VERSION}.tar.gz | tar --strip-components 1 -xz || \
```

`apt-get purge` is equivalent to `apt-get remove --purge` and will remove user data/configuration files. Above we are also creating folder in desired directory and install Asterisk source code from the Asterisk repository.

```
#!/bin/bash
PROGNAME=$(basename $0)

if test -z ${ASTERISK_VERSION}; then
  echo "${PROGNAME}: ASTERISK_VERSION required" >&2
  exit 1
fi

set -ex

useradd --system asterisk

apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends --no-install-suggests \
    autoconf \
    binutils-dev \
    build-essential \
    ca-certificates \
    curl \
    file \
    libcurl4-openssl-dev \
    libedit-dev \
    libgsm1-dev \
    libogg-dev \
    libpopt-dev \
    libresample1-dev \
    libspandsp-dev \
    libspeex-dev \
    libspeexdsp-dev \
    libsqlite3-dev \
    libsrtp2-dev \
    libssl-dev \
    libvorbis-dev \
    libxml2-dev \
    libxslt1-dev \
    procps \
    portaudio19-dev \
    unixodbc \
    unixodbc-bin \
    unixodbc-dev \
    odbcinst \
    uuid \
    uuid-dev \
    xmlstarlet
    
apt-get purge -y --auto-remove
rm -rf /var/lib/apt/lists/*

mkdir -p /usr/src/asterisk
cd /usr/src/asterisk

curl -vsL http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-${ASTERISK_VERSION}.tar.gz | tar --strip-components 1 -xz || \

# 1.5 jobs per core works out okay
: ${JOBS:=$(( $(nproc) + $(nproc) / 2 ))}

./configure --with-resample \
            --with-pjproject-bundled \
            --with-jansson-bundled
make menuselect/menuselect menuselect-tree menuselect.makeopts
```

`${JOBS:=$(( $(nproc) + $(nproc) / 2 ))}` ensures performance and load balancing. Use `./configure` and related parameters to make Asterisk ready for configuration.

####6.Compiling Asterisk Modules 

The next step in the build process is to tell Asterisk which modules to compile and install, as well as set various compiler options. These settings are all controlled via a menu-driven system called **Menuselect** through interactive installation. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/n2j0mecghujqy6e1t5rv.png)

Options in **Menuselect** can be controlled from the command line. **Menuselect** can be built without invoking the user interface via the `menuselect.makeopts` as shown in the scipt below - 

```
make menuselect/menuselect menuselect-tree menuselect.makeopts

# disable BUILD_NATIVE to avoid platform issues
menuselect/menuselect --disable BUILD_NATIVE menuselect.makeopts

# enable required modules
menuselect/menuselect --enable BETTER_BACKTRACES menuselect.makeopts

# enable ooh323
menuselect/menuselect --enable chan_ooh323 menuselect.makeopts

# codecs
# menuselect/menuselect --enable codec_opus menuselect.makeopts
# menuselect/menuselect --enable codec_silk menuselect.makeopts

# # download more sounds
# for i in CORE-SOUNDS-EN MOH-OPSOUND EXTRA-SOUNDS-EN; do
#     for j in ULAW ALAW G722 GSM SLN16; do
#         menuselect/menuselect --enable $i-$j menuselect.makeopts
#     done
# done

# we don't need any sounds in docker, they will be mounted as volume
menuselect/menuselect --disable-category MENUSELECT_CORE_SOUNDS menuselect.makeopts
menuselect/menuselect --disable-category MENUSELECT_MOH menuselect.makeopts
menuselect/menuselect --disable-category MENUSELECT_EXTRA_SOUNDS menuselect.makeopts
```

As shown above, some modules have been enabled/disabled as required using `menuselect.makeopts`. 

```
make -j ${JOBS} all
make install

# copy default configs
# cp /usr/src/asterisk/configs/basic-pbx/*.conf /etc/asterisk/
make samples

# set runuser and rungroup
sed -i -E 's/^;(run)(user|group)/\1\2/' /etc/asterisk/asterisk.conf

# Install opus
mkdir -p /usr/src/codecs/opus \
  && cd /usr/src/codecs/opus \
  && curl -vsL http://downloads.digium.com/pub/telephony/codec_opus/${OPUS_CODEC}.tar.gz | tar --strip-components 1 -xz \
  && cp *.so /usr/lib/asterisk/modules/ \
  && cp codec_opus_config-en_US.xml /var/lib/asterisk/documentation/

mkdir -p /etc/asterisk/ \
         /var/spool/asterisk/fax

chown -R asterisk:asterisk /etc/asterisk \
                           /var/*/asterisk \
                           /usr/*/asterisk
chmod -R 750 /var/spool/asterisk

cd /
rm -rf /usr/src/asterisk \
       /usr/src/codecs
```

With `make install` we are finishing `menuselect` and the build of our Asterisk image. Additionally the `sed` command will modify **asterisk.conf** and `-E` add the script to be executed. 

```
# remove *-dev packages
devpackages=`dpkg -l|grep '\-dev'|awk '{print $2}'|xargs`
DEBIAN_FRONTEND=noninteractive apt-get --yes purge \
  autoconf \
  build-essential \
  bzip2 \
  cpp \
  m4 \
  make \
  patch \
  perl \
  perl-modules \
  pkg-config \
  xz-utils \
  ${devpackages}
rm -rf /var/lib/apt/lists/*

exec rm -f /build-asterisk.sh
```

Finally clean the Dev packages(if any) from the Docker image. That's it! 

Let us go back to the Dockerfile and continue creating our image.

```
#base image for container
FROM debian:buster-slim

LABEL maintainer='Bora Ozkan <boraozkan@gmail.com>'

ENV ASTERISK_VERSION 17-current
ENV OPUS_CODEC       asterisk-17.0/x86-64/codec_opus-17.0_current-x86_64

COPY build-asterisk.sh /
RUN /build-asterisk.sh

EXPOSE 5060/udp 5060/tcp
VOLUME /var/lib/asterisk/sounds /var/lib/asterisk/keys\                		  /var/lib/asterisk/phoneprov /var/spool/asterisk\    			  		 /var/log/asterisk

COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/usr/sbin/asterisk", "-vvvdddf", "-T", "-W", "-U", "asterisk", "-p"]
```

`EXPOSE` informs Docker that the container listens on the specified network ports during runtime. You can specify whether the port listens on TCP or UDP, where the default is TCP if the protocol is not specified. Use the `VOLUME` instruction to create a mount point with the specified name and mark it as holding externally mounted volumes from native host or other containers. We can  also add custom codec, sound and log from our local directory to the image.

Additionally, `ENTRYPOINT` allows you to configure a container that will run as an executable and will start Asterisk when Docker run is executed. Let us put some additional commands in `docker-entrypoint.sh` - 

```
#!/bin/sh

# run as user asterisk by default
ASTERISK_USER=${ASTERISK_USER:-asterisk}

if [ "$1" = "" ]; then
  COMMAND="/usr/sbin/asterisk -T -W -U ${ASTERISK_USER} -p -vvvdddf"
else
  COMMAND="$@"
fi

if [ "${ASTERISK_UID}" != "" ] && [ "${ASTERISK_GID}" != "" ]; then
  # recreate user and group for asterisk
  # if they've sent as env variables (i.e. to macth with host user to fix permissions for mounted folders

  deluser asterisk && \
  adduser --gecos "" --no-create-home --uid ${ASTERISK_UID} --disabled-password ${ASTERISK_USER} || exit

  chown -R ${ASTERISK_UID}:${ASTERISK_UID} /etc/asterisk \
                                           /var/*/asterisk \
                                           /usr/*/asterisk
fi

exec ${COMMAND}
```

The above script will create an Asterisk user for us, also checking if user is working with correct permissions. With this we finish our Dockerfile script which will help installing and configuring Asterisk. Now it is time to build our image from the Dockerfile.

```
docker build -t asterisk:latest .
```

With this command you are creating image from the Dockerfile.

```
#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
asterisk            latest              e275d4a274de        4 minutes ago       421MB
```

As shown above, Asterisk image created is now of 421Mb as we added certain modules and installation scripts. 

####7.Testing the Asterisk image - 

Let us test the Asterisk image by starting our container with the *Expose Port* parameter. Run your container with the command below and you should see an output similar to this:

```
docker run -p 5060:5060 asterisk:latest
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/8jnvqvotqeugipov35ft.png)

The port 5060 should be reachable now which you can test further by registering with a softphone. It is however important that you expose a range of ports when running the container using `-P` (capital P). Normally when you start a container it is reachable from container to internet but cannot reach from outside to container. In this case, if you use `-P` with `docker run`, the port will be exposed once for TCP and once for UDP. Remember that `-P` uses an ephemeral high-ordered host port on the host, so the port will not be the same for TCP and UDP.

```
docker run -P asterisk:latest
```

Now we are ready to push our images to our **Docker Hub** account; which we will use for Fargate and ECR in AWS Cloud.

```
docker login --username=yourhubusername --email=youremail@company.com
```

After succesfully login to the docker hub account we are ready to push our images to the hub - 

```
docker tag e275d4a274de boraozkan/asterisk_fargate:firsttry
```

It is also advised to tag your images to make it easier to remember as above. 

```
#docker push boraozkan/asterisk_fargate
The push refers to repository [docker.io/boraozkan/asterisk_fargate]81fa04b8a12f: Pushed24243a5e2b77: Pushing  45.21MB/352.1MB23d7848c4bd6: Pushed556c5fb0d91b: Mounted from library/debian
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/x00mshj5l2kd8hb39r6a.png)

#Deploying Asterisk Docker Image on Fargate through ECR#

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/oc3t79ohz0d9hzv41nfq.png)

####1. Setting up AWS EC2 image for Asterisk -  

a. Let us start by creating an EC2 instance which will host our Asterisk image and registering it to the ECR. 
b. Open AWS console and launch a new instance on EC2 - 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vhs18dht3j4vu79rtc83.png)

c. Select **Amazon Linux 2 AMI and choose free-tier instance** t2.nano or t2.micro (as per your choice). Follow instructions and launch machine. Keep your PEM file which we will need while login to SSH. Navigate to EC2 console again and wait a couple of minutes until the new instance gets ready. Click new instance when it is available, following which copy the IP (ours is 35.153.102.33 as shown below) - 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/25bc8axr4vmiwrlfap01.png)

d. After creating the instance, assign IAM Role to the instance which essentially gives permission to access ECR(Elastic Container Registry) service. For doing the above, you can go to Action Menu > Instance Settings > Attach/Replace IAM Role

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/rooyddxv4bh7iwwu5kgh.png)

e. Choose EC2 >> Go to next page >> Search for 'elastic container service' >> Apply for this permission >> Assign a name tag for ease of remembrance.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mktco2h2t8dd826ckdi9.png)

f. Choose EC2 IAM role from the console >> Click on Apply.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vi3dkzmvj1bj1bt71xn6.png)

g. Login instance through SSH.

```
ssh -i xxx.pem ec2-user@35.153.102.33

The authenticity of host '35.153.102.33 (35.153.102.33)' can't be established.ECDSA key fingerprint is SHA256:PAQBN8RnB8YeP/eOG/VoJEmn4ipTpZAoZ/0Lb9rgOx8.Are you sure you want to continue connecting (yes/no)? yesWarning: Permanently added '35.153.102.33' (ECDSA) to the list of known hosts.

https://aws.amazon.com/amazon-linux-2/2 package(s) needed for security, out of 13 availableRun "sudo yum update" to apply all updates.[ec2-user@ip-172-31-39-17 ~]$
```

Change your PEM file name as per your convenience >> Assign permission with `chmod` 600 or 700 >> Login to a fresh instance >> Make necessary updates on instance as required.

`[ec2-user@ip-172-31-39-17 ~]$ sudo yum -y update`

`[ec2-user@ip-172-31-39-17 ~]$ sudo amazon-linux-extras install docker`

`[ec2-user@ip-172-31-39-17 ~]$ sudo service docker start`

`[ec2-user@ip-172-31-39-17 ~]$ sudo usermod -a -G docker ec2-user`

`[ec2-user@ip-172-31-39-17 ~]$ sudo docker info`

`sudo docker login`

Enter your credentials and then extract the Asterisk image which we created on Docker hub.

```
[ec2-user@ip-172-31-39-17 ~]$ sudo docker pull boraozkan/asterisk_fargate:firsttry
firsttry: Pulling from boraozkan/asterisk_fargate
8ec398bc0356: Pull complete 
cfb6ad1933f7: Pull complete 
3ac5bd4b41b7: Pull complete 
985634a4d9b2: Pull complete 
Digest: sha256:f519a1f04018f34f0e17380492a0722adf360c9e2f021a951d7acaa3a7533c4d
Status: Downloaded newer image for boraozkan/asterisk_fargate:firsttry
[ec2-user@ip-172-31-39-17 ~]$ 
```

The Asterisk image is now on our EC2 instance -  

```
[ec2-user@ip-172-31-39-17 ~]$ sudo docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
boraozkan/asterisk_fargate   firsttry            e275d4a274de        19 hours ago        421MB
[ec2-user@ip-172-31-39-17 ~]$ 
```

The next step is to push this image to ECR, however before pushing it to ECR we need to first create a repository in ECR. 

####2. Creating ECR Repository on AWS EC2 - 

a. Go to the ECR console and create a repository.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/zwgwcd5eh57pjtfk8gzn.png)

b. Copy the URI after create the repository 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7m5sftrl9zmgzcosioiz.png)

c. Tag your image with this URI in EC2 SSH CLI. Note that we now have two images; one the originally configured Asterisk image while the second one is the one which we tagged in ECR.

```
[ec2-user@ip-172-31-39-17 ~]$ sudo docker tag boraozkan/asterisk_fargate:firsttry 312867154612.dkr.ecr.us-east-1.amazonaws.com/asterisk
[ec2-user@ip-172-31-39-17 ~]$ sudo docker images
REPOSITORY                                              TAG                 IMAGE ID            CREATED             SIZE
312867154612.dkr.ecr.us-east-1.amazonaws.com/asterisk   latest              e275d4a274de        19 hours ago        421MB
boraozkan/asterisk_fargate                              firsttry            e275d4a274de        19 hours ago        421MB
[ec2-user@ip-172-31-39-17 ~]$ 
```

d. Login to ECR from EC2 AWS CLI >> Keep note of the long key.

```
[ec2-user@ip-172-31-39-17 ~]$ aws ecr get-login --no-include-email --region us-east-1
docker login -u AWS -p eyJwYXlsb2FkIjoiVFd5UVc4UXhmZ1R0WnFNY1FZd25ITVVTcVZTOFlvZHo2L0l6SDNQMGpCUHpSOFJ1c3JvSjRNems1OFI1ak5kY2QwQldnN
```

e. Copy the portion - `docker login -u AWS -p eyJwYXlsb2FkIjoiVFd5UVc4UXhmZ1R0WnFNY1FZd25ITVVTcVZTOFlvZHo2L0l6SDNQMGpCUHpSOFJ1c3JvSjRNems1OFI1ak5kY2QwQldnN` and paste to SSH CLI to login to ECR

f. We are ready to push our image to ECR Repo now. Use URI which was copied during the creation of the ECR repository.

```
[ec2-user@ip-172-31-39-17 ~]$ sudo docker push 312867154612.dkr.ecr.us-east-1.amazonaws.com/asterisk
The push refers to repository [312867154612.dkr.ecr.us-east-1.amazonaws.com/asterisk]
81fa04b8a12f: Pushed 
24243a5e2b77: Pushed 
23d7848c4bd6: Pushed 
556c5fb0d91b: Pushed 
latest: digest: sha256:f519a1f04018f34f0e17380492a0722adf360c9e2f021a951d7acaa3a7533c4d size: 1157
[ec2-user@ip-172-31-39-17 ~]$ 
```

g. Check ECR Repo for the Asterisk image. Once we see it there, we are can now deploy the image to Fargate. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/maxotxbr1no3xl1ppiza.png)

####3.Deploying Asterisk image to Fargate -

a. On the AWS main console's ECS page click on 'Get Started' and you will be in the screen as below - 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/d8aw4p0qctvvfmcpe5c2.png)

b. Start configuring by giving a name to the container >> Assign a Task >> Select 'Custom' container definition >> Type the Image URI Container name and expose ports.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/m9x8855ljfyzmgy4uw3c.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/94mtzc875smmowjrko1o.png)

c. Assign Default for every other options.  For the reference of this article, we are not assigning any Load Balancer in this project

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/39rxpi52loasokepmfxy.png)

d. Leave Default Cluster Configuration - 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/uua7a8crtowtgh8ft45m.png)

e. Check reviews and create Fargate. Once finished, go back to the *Service View*

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/kk7d85ii74qx8a4ilp49.png)

f. Use a softphone and test by trying to register.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/zmqhvdk3i4e2q2emrk71.png)

#Conclusion#

Hopefully you can now understand and use your Asterisk image to deploy your PBX with Fargate. In another topic we will go through the steps of arranging your Asterisk RTP for voice transfer.